Home > Software engineering >  I have a problem passing props from a state to the child
I have a problem passing props from a state to the child

Time:01-26

This is the Login component where I created the authentication state with the token as false, and after login convert as true

function Login() {
  const [user, setUser] = useState({ name: '', email: '' });
  const [error, setError] = useState('');
  const [auth, setAuth] = useState({ token: false })
  console.log(auth)
  const Login = (details) => {
    console.log(details);
    if (
      details.name === adminUser.name &&
      details.email === adminUser.email &&
      details.password === adminUser.password
    ) {
      console.log('Logged in');
      setAuth({
        token: true,
      })

This works perfectly fine, but now when I try to pass it to the PrivateRoute component, the auth is undefined

const PrivateRoutes = ({ auth }) => {
  console.log(auth)
  return (
    auth ? <Outlet/> : <Navigate to="/login"/>
  )
}

Also this is my App.jsx

function App() {
  return (
    <Routes>
      <Route element={<PrivateRoutes />}>
        <Route path="/*" element={<MainPage />} />
      </Route>
      <Route path="/login" element={<Login />} />
    </Routes>
  );
}

What do I need to change to get the data from the state and my guard functionality to work?

CodePudding user response:

The auth state should be in a common ancestor so it can be passed down as props.

Example:

function App() {
  const [auth, setAuth] = useState({ token: false });

  return (
    <Routes>
      <Route element={<PrivateRoutes auth={auth} />}>
        <Route path="/*" element={<MainPage />} />
      </Route>
      <Route path="/login" element={<Login setAuth={setAuth} />} />
    </Routes>
  );
}
const PrivateRoutes = ({ auth }) => {
  return auth.token ? <Outlet/> : <Navigate to="/login" replace />;
}
function Login({ setAuth }) {
  const navigate = useNavigate();

  const [user, setUser] = useState({ name: '', email: '' });
  const [error, setError] = useState('');

  const login = (details) => {
    if (
      details.name === adminUser.name &&
      details.email === adminUser.email &&
      details.password === adminUser.password
    ) {
      setAuth({ token: true });
      navigate(/* new target path */, { replace: true });

    ...
  }

  ...

CodePudding user response:

So, to summarise, you want the state in the Login component to be able to access in PrivateRoutes component. React recommends a pattern called lifting state up to achieve such similar use cases .

The idea is to have the auth state variable in common parent to both LoginPage component and PrivateRoute Component and pass it to both child components.

Something similar to the below image

enter image description here

So now changing auth (state) in any one of the components will effect the other component too. You should pass down setAuth() to the component where you want to modify the auth state.

In your example, Login component must be able to modify auth so that PrivateRoute component can use that state. You need to pass setAuth() to Login component and auth variable to PrivateRoute

Refer the docs here

The answer by Drew Reese makes it clear with the code example. Please refer it.

  • Related