30

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

Logan Klein
  • 333
  • 1
  • 3
  • 4

2 Answers2

89

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.

catamphetamine
  • 4,489
  • 30
  • 25
3

You don't need to use useMemo. It will duplicate what Provider already accomplishes. Instead

return <AuthDataContext.Provider value={{ authData, onLogin, onLogout }} {...props} />;
SILENT
  • 3,916
  • 3
  • 38
  • 57