I'm trying to use context to create a authentication provider for my app. Following a guide for Authentication with react router and react hooks. It's using a memo to fetch authentication if auth changes.
This is the guide i was following https://medium.com/trabe/implementing-private-routes-with-react-router-and-hooks-ed38d0cf93d5
I've tried looking up the error and working around the memo to no avail.
Here is my provider
const AuthDataContext = createContext(null)
const initialAuthData = {}
const AuthDataProvider = props => {
const [authData, setAuthData] = useState(initialAuthData)
useEffect(() => {
async function getAuth(){
let currentAuthData = await fetch("URL/api/v1/logged_in", {
method: "GET",
credentials: "include",
headers: {
Accept: "application/json",
"Content-Type": "application/json"
}
})
.then(res => res.json())
.then(data => (data))
.catch(error => console.error("Error:", error));
if(currentAuthData) {
setAuthData(currentAuthData)
}
};
getAuth()
},[])
const onLogout = () => setAuthData(initialAuthData);
const onLogin = newAuthData => setAuthData(newAuthData);
const authDataValue = useMemo({ ...authData, onLogin, onLogout }, [authData]);
return <AuthDataContext.Provider value={authDataValue} {...props} />;
};
export const useAuthDataContext = () => useContext(AuthDataContext);
The PrivateRoute component
const PrivateRoute = ({ component, ...options }) => {
const { user } = useAuthDataContext();
const finalComponent = user ? component : SignInPage;
return <Route {...options} component={finalComponent} />;
};
The AuthProvider wrapping my app
const MyApp = props => (
<BrowserRouter>
<AuthDataProvider>
<App />
</AuthDataProvider>
</BrowserRouter>
);
I expected the auth provider to fetch the user and Logged_In status and provide it to child components. The private route to see the authData from the context api and only render the route if the user is logged in. Thanks in advance!
The useMemo is throwing this error nextCreate is not a function mountMemo
13962 | var hook = mountWorkInProgressHook();
13963 | var nextDeps = deps === undefined ? null : deps;
> 13964 | var nextValue = nextCreate();
| ^ 13965 | hook.memoizedState = [nextValue, nextDeps];
13966 | return nextValue;
13967 | }
View compiled
Use useMemo To fix this performance issue, we can use the useMemo Hook to memoize the expensiveCalculation function. This will cause the function to only run when needed. We can wrap the expensive function call with useMemo . The useMemo Hook accepts a second parameter to declare dependencies.
React has a built-in hook called useMemo that allows you to memoize expensive functions so that you can avoid calling them on every render. You simple pass in a function and an array of inputs and useMemo will only recompute the memoized value when one of the inputs has changed.
The useMemo is a hook used in the functional component of react that returns a memoized value. In Computer Science, memoization is a concept used in general when we don't need to recompute the function with a given argument for the next time as it returns the cached result.
useMemo is very similar to useCallback. It accepts a function and a list of dependencies, but the difference between useMemo and useCallback is that useMemo returns the memo-ized value returned by the passed function. It only recalculates the value when one of the dependencies changes.
The "nextCreate is not a function"
error is thrown when you're not passing a function as a useMemo()
argument.
For example, useMemo(123, [])
will throw and useMemo(() => 123, [])
won't.
You don't need to use useMemo
. It will duplicate what Provider already accomplishes.
Instead
return <AuthDataContext.Provider value={{ authData, onLogin, onLogout }} {...props} />;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With