|
1 | 1 | # react-netlify-identity
|
2 | 2 |
|
3 |
| -> use netlify identity with react |
| 3 | +> Netlify Identity + React Hooks, with Typescript |
4 | 4 |
|
5 | 5 | [](https://www.npmjs.com/package/react-netlify-identity) [](https://standardjs.com)
|
6 | 6 |
|
| 7 | +Use [Netlify Identity](https://www.netlify.com/docs/identity/) easier with React! This is a thin wrapper over the [gotrue-js](https://github.com/netlify/gotrue-js) library for easily accessing Netlify Identity functionality in your app, with React Hooks. Types are provided. |
| 8 | + |
| 9 | +You can find [a full demo here](https://netlify-gotrue-in-react.netlify.com/) with [source code](https://github.com/netlify/create-react-app-lambda/tree/reachRouterAndGoTrueDemo/src). |
| 10 | + |
| 11 | +**This library is not officially maintained by Netlify.** This is written by swyx for his own use (and others with like minds 😎). See below for official alternatives. |
| 12 | + |
| 13 | +## Official Alternatives |
| 14 | + |
| 15 | +This is a "headless" library, meaning there is no UI exported and you will write your own UI to work with the authentication. |
| 16 | + |
| 17 | +If you want to use the official Javascript bindings to GoTrue, Netlify's underlying Identity service written in Go, use https://github.com/netlify/gotrue-js |
| 18 | + |
| 19 | +If you want a "widget" overlay that gives you a nice UI out of the box, at the cost of a larger bundle, check https://github.com/netlify/netlify-identity-widget |
| 20 | + |
| 21 | +If you want a popup window approach also with a nice UI out of the box, and don't mind the popup flow, check https://github.com/netlify/netlify-auth-providers |
| 22 | + |
| 23 | +## Typescript |
| 24 | + |
| 25 | +Library is written in Typescript. File an issue if you find any problems. |
| 26 | + |
7 | 27 | ## Install
|
8 | 28 |
|
9 | 29 | ```bash
|
10 |
| -npm install --save react-netlify-identity |
| 30 | +yarn add react-netlify-identity |
11 | 31 | ```
|
12 | 32 |
|
13 | 33 | ## Usage
|
14 | 34 |
|
| 35 | +**As a React Hook**, you can destructure these variables and methods: |
| 36 | + |
| 37 | +- `user: User` |
| 38 | +- `setUser`: directly set the user object. Not advised; use carefully!! mostly you should use the methods below |
| 39 | +- `isConfirmedUser: boolean`: if they have confirmed their email |
| 40 | +- `isLoggedIn: boolean`: if the user is logged in |
| 41 | +- `signupUser(email: string, password: string, data: Object)` |
| 42 | +- `loginUser(email: string, password: string)` |
| 43 | +- `logoutUser()` |
| 44 | +- `requestPasswordRecovery(email: string)` |
| 45 | +- `recoverAccount(token: string, remember?: boolean | undefined)` |
| 46 | +- `updateUser(fields: Object)` |
| 47 | +- `getFreshJWT()` |
| 48 | +- `authedFetch(endpoint: string, obj = {})` (a thin axios-like wrapper over `fetch` that has the user's JWT attached, for convenience pinging Netlify Functions with Netlify Identity) |
| 49 | + |
| 50 | +<details> |
| 51 | +<summary> |
| 52 | +<b> |
| 53 | +Example code |
| 54 | +</b> |
| 55 | +</summary> |
| 56 | + |
15 | 57 | ```tsx
|
16 |
| -import * as React from 'react' |
| 58 | +import * as React from 'react'; |
17 | 59 |
|
18 |
| -import MyComponent from 'react-netlify-identity' |
| 60 | +import { useNetlifyIdentity } from './useNetlifyIdentity'; |
19 | 61 |
|
20 |
| -class Example extends React.Component { |
21 |
| - render () { |
22 |
| - return ( |
23 |
| - <MyComponent /> |
24 |
| - ) |
25 |
| - } |
| 62 | +const IdentityContext = React.createContext(); // not necessary but recommended |
| 63 | +function App() { |
| 64 | + const identity = useNetlifyIdentity(url); |
| 65 | + return ( |
| 66 | + <IdentityContext.Provider value={identity}> |
| 67 | + {/* rest of your app */} |
| 68 | + </IdentityContext.Provider> |
| 69 | + ); |
26 | 70 | }
|
| 71 | + |
| 72 | +// log in/sign up example |
| 73 | +function Login() { |
| 74 | + const { loginUser, signupUser } = React.useContext(IdentityContext); |
| 75 | + const formRef = React.useRef(); |
| 76 | + const [msg, setMsg] = React.useState(''); |
| 77 | + const [isLoading, load] = useLoading(); |
| 78 | + const signup = () => { |
| 79 | + const email = formRef.current.email.value; |
| 80 | + const password = formRef.current.password.value; |
| 81 | + load(signupUser(email, password)) |
| 82 | + .then(user => { |
| 83 | + console.log('Success! Signed up', user); |
| 84 | + navigate('/dashboard'); |
| 85 | + }) |
| 86 | + .catch(err => console.error(err) || setMsg('Error: ' + err.message)); |
| 87 | + }; |
| 88 | + return ( |
| 89 | + <form |
| 90 | + ref={formRef} |
| 91 | + onSubmit={e => { |
| 92 | + e.preventDefault(); |
| 93 | + const email = e.target.email.value; |
| 94 | + const password = e.target.password.value; |
| 95 | + load(loginUser(email, password)) |
| 96 | + .then(user => { |
| 97 | + console.log('Success! Logged in', user); |
| 98 | + navigate('/dashboard'); |
| 99 | + }) |
| 100 | + .catch(err => console.error(err) || setMsg('Error: ' + err.message)); |
| 101 | + }} |
| 102 | + > |
| 103 | + <div> |
| 104 | + <label> |
| 105 | + Email: |
| 106 | + <input type="email" name="email" /> |
| 107 | + </label> |
| 108 | + </div> |
| 109 | + <div> |
| 110 | + <label> |
| 111 | + Password: |
| 112 | + <input type="password" name="password" /> |
| 113 | + </label> |
| 114 | + </div> |
| 115 | + {isLoading ? ( |
| 116 | + <Spinner /> |
| 117 | + ) : ( |
| 118 | + <div> |
| 119 | + <input type="submit" value="Log in" /> |
| 120 | + <button onClick={signup}>Sign Up </button> |
| 121 | + {msg && <pre>{msg}</pre>} |
| 122 | + </div> |
| 123 | + )} |
| 124 | + </form> |
| 125 | + ); |
| 126 | +} |
| 127 | + |
| 128 | +// log out user |
| 129 | +function Logout() { |
| 130 | + const { logoutUser } = React.useContext(IdentityContext); |
| 131 | + return <button onClick={logoutUser}>You are signed in. Log Out</button>; |
| 132 | +} |
| 133 | + |
| 134 | +// check `identity.user` in a protected route |
| 135 | +function PrivateRoute(props) { |
| 136 | + const identity = React.useContext(IdentityContext); |
| 137 | + let { as: Comp, ...rest } = props; |
| 138 | + return identity.user ? ( |
| 139 | + <Comp {...rest} /> |
| 140 | + ) : ( |
| 141 | + <div> |
| 142 | + <h3>You are trying to view a protected page. Please log in</h3> |
| 143 | + <Login /> |
| 144 | + </div> |
| 145 | + ); |
| 146 | +} |
| 147 | + |
| 148 | +// check if user has confirmed their email |
| 149 | +// use authedFetch API to make a request to Netlify Function with the user's JWT token, |
| 150 | +// letting your function use the `user` object |
| 151 | +function Dashboard() { |
| 152 | + const props = React.useContext(IdentityContext); |
| 153 | + const { isConfirmedUser, authedFetch } = props; |
| 154 | + const [isLoading, load] = useLoading(); |
| 155 | + const [msg, setMsg] = React.useState('Click to load something'); |
| 156 | + const handler = () => { |
| 157 | + load(authedFetch.get('/.netlify/functions/authEndPoint')).then(setMsg); |
| 158 | + }; |
| 159 | + return ( |
| 160 | + <div> |
| 161 | + <h3>This is a Protected Dashboard!</h3> |
| 162 | + {!isConfirmedUser && ( |
| 163 | + <pre style={{ backgroundColor: 'papayawhip' }}> |
| 164 | + You have not confirmed your email. Please confirm it before you ping |
| 165 | + the API. |
| 166 | + </pre> |
| 167 | + )} |
| 168 | + <hr /> |
| 169 | + <div> |
| 170 | + <p>You can try pinging our authenticated API here.</p> |
| 171 | + <p> |
| 172 | + If you are logged in, you should be able to see a `user` info here. |
| 173 | + </p> |
| 174 | + <button onClick={handler}>Ping authenticated API</button> |
| 175 | + {isLoading ? <Spinner /> : <pre>{JSON.stringify(msg, null, 2)}</pre>} |
| 176 | + </div> |
| 177 | + </div> |
| 178 | + ); |
| 179 | +} |
| 180 | +``` |
| 181 | + |
| 182 | +This is also exported as a render prop component, `NetlifyIdentity`, but we're not quite sure if its that useful if you can already use hooks: |
| 183 | + |
| 184 | +```tsx |
| 185 | +<NetlifyIdentity domain="https://mydomain.netlify.com"> |
| 186 | + {({ loginUser, signupUser }) => { |
| 187 | + // use it |
| 188 | + }} |
| 189 | +</NetlifyIdentity> |
27 | 190 | ```
|
28 | 191 |
|
| 192 | +</details> |
| 193 | + |
29 | 194 | ## License
|
30 | 195 |
|
31 | 196 | MIT © [sw-yx](https://github.com/sw-yx)
|
0 commit comments