skip to Main Content

My goal is to control the user’s data from the login page via the fakeAPI and pass it to the movies page, but after passing the user information, these errors appear before a blank page comes up.

/* eslint-disable no-unused-vars */
/* eslint-disable no-undef */
// App.js
import React, { useState } from 'react';
import { BrowserRouter as Router, Route, Routes} from 'react-router-dom';
import Login from './components/Login';
import MovieList from './components/MovieList';

const App = () => {
  const [loggedIn, setLoggedIn] = useState(false);
  const [user, setUser] = useState(null);

  const handleLogin = async (username, password) => {
    // Simulate user authentication using the fake API
    const users = await fetchUsers();
    const matchedUser = users.find(
      (user) => user.username === username && user.password === password
    );

    if (matchedUser) {
      setLoggedIn(true);
      setUser(matchedUser);
    } else {
      alert('Invalid credentials. Please try again.');
    }
  };

  const handleLogout = () => {
    setLoggedIn(false);
    setUser(null);
  };

  return (
    <Router>
        <Routes>
          {/* Login page */}
          <Route path="/" element={loggedIn ? <Route to="/movies" /> : <Login onLogin={handleLogin} />} />

          {/* MovieList page */}
          <Route path="/movies" element={loggedIn ? <MovieList user={user} onLogout={handleLogout} /> : <Route to="/movies" />} />
        </Routes>
    </Router>
  );
};

export default App;

I dont understand what those mean.

Error image:
Cannot destructure property ‘loggedIn’ of ‘user’ as it is null.
TypeError: Cannot destructure property ‘loggedIn’ of ‘user’ as it is null.
at MovieList (http://localhost:3000/static/js/bundle.js:414:5)
at renderWithHooks (http://localhost:3000/static/js/bundle.js:25955:22)
at mountIndeterminateComponent (http://localhost:3000/static/js/bundle.js:29241:17)
at beginWork (http://localhost:3000/static/js/bundle.js:30537:20)
at HTMLUnknownElement.callCallback (http://localhost:3000/static/js/bundle.js:15547:18)
at Object.invokeGuardedCallbackDev (http://localhost:3000/static/js/bundle.js:15591:20)
at invokeGuardedCallback (http://localhost:3000/static/js/bundle.js:15648:35)
at beginWork$1 (http://localhost:3000/static/js/bundle.js:35522:11)
at performUnitOfWork (http://localhost:3000/static/js/bundle.js:34769:16)
at workLoopSync (http://localhost:3000/static/js/bundle.js:34692:9)

2

Answers


  1. Here’s how you should structure your routes using the Routes and Route components:

    import React, { useState } from 'react';
    import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
    import Login from './components/Login';
    import MovieList from './components/MovieList';
    
    const App = () => {
    const [loggedIn, setLoggedIn] = useState(false);
    const [user, setUser] = useState(null);
    
    const handleLogin = async (username, password) => {
        // Simulate user authentication using the fake API
        const users = await fetchUsers();
        const matchedUser = users.find(
        (user) => user.username === username && user.password === password
        );
    
        if (matchedUser) {
        setLoggedIn(true);
        setUser(matchedUser);
        } else {
        alert('Invalid credentials. Please try again.');
        }
    };
    
    const handleLogout = () => {
        setLoggedIn(false);
        setUser(null);
    };
    
    return (
        <Router>
        <Routes>
            {/* Login page */}
            <Route path="/" element={loggedIn ? <Navigate to="/movies" /> : <Login onLogin={handleLogin} />} />
    
            {/* MovieList page */}
            <Route path="/movies" element={<MovieList user={user} onLogout={handleLogout} />} />
        </Routes>
        </Router>
    );
    };
    
    export default App;
    
    Login or Signup to reply.
  2. it looks like you want to redirect a user if they’re not logged in. This is possible, but your implementation is flawed. When you write <Component /> the component is rendered when the containing function is called.

    When you wrote <Route path="/" element={loggedIn ? <Route to="/movies" /> : <Login onLogin={handleLogin} />} />

    <Route to="/movies" /> is rendered, hence the error you’re receiving.

    You should leverage the <Navigate /> component, the documentation has a similar example to your code: https://reactrouter.com/en/main/components/navigate

    While this is a misuse of react-router, I’ve seen a lot of engineers thrown off because they did not understand the error. The real issue here is that you did not realize you were rendering the Route component as specified in the error.

    This should work:
    <Route path="/" element={loggedIn ? <Navigate to="/movies" /> : <Login onLogin={handleLogin} />} />

    Updated error

    Cannot destructure property ‘loggedIn’ of ‘user’ as it is null.
    TypeError: Cannot destructure property ‘loggedIn’ of ‘user’ as it is
    null. at MovieList

    This line is throwing the error: <Route path="/movies" element={loggedIn ? <MovieList user={user} onLogout={handleLogout} /> : <Route to="/movies" />} />

    loggedIn is true but user is null. In general, it’s important to know when a value is derived. loggedIn indicates whether there is a user, so derive its value from user.

    const loggedIn = useMemo(()=> !!user, [user]);
    // i really prefer starting bools with "is" => isLoggedIn
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search