4

I'm facing a bit of a problem for the last 2 days and I'm not sure what I do wrong.
I want to implement a login page that redirects the user to the dashboard after login.
Because I want to use the username across the application I stored the value in the App.js.
The value is passed to the Login.js, there I try to call setUsername function to update the value, but after the redirection the value is null again. Shouldn't the value of username be the one that was set with setUsername??

App.js

const App = () => {
    const [username, setUsername] = useState(null);

    return (
        <div className="site">
            <main>
                <Switch>
                    <Route exact path={'/login'} render={() => <Login username={username} setUsername={setUsername} />} />
                    <Route exact path={'/dashboard/:username'} render={() => <Dashboard username={username} />}/>
                </Switch>
            </main>
        </div>
    );
};

Login.js

const Login = (props) => {
    let username = props.username;
    const [password, setPassword] = useState("");

    function handleSubmit(e) {
        e.preventDefault();
        axiosInstance.post('url', {
            username: username,
            password: password
        }).then(response => {
                props.setUsername(username);
             }
        ).then(() => window.location = `/dashboard/${username}`)
            .catch(error => {
             throw error;
        });
    }

    return (
        <MyForm onSubmit={handleSubmit}>
            <Form.Group controlId="formBasicUser">
                <Form.Label>Username</Form.Label>
                <Form.Control type="text" name="username" value={username} placeholder="Enter username" onChange={(e) => props.setUsername(e.target.value)}/>
            </Form.Group>

            <Form.Group controlId="formBasicPassword">
                <Form.Label>Password</Form.Label>
                <Form.Control type="password" name="password" value={password} placeholder="Password" onChange={e => setPassword(e.target.value)}/>
            </Form.Group>
            <Button variant="primary" type="submit">
                Login
            </Button>
        </MyForm>
    );
};

I tried also setting the username in the submit function but... nada

Dashboard.js

const Dashboard = (props) => {
    return (
        <h1>Welcome {props.username}</h1>
    );
};
  • You are passing the function but not updating the value – Learner Jun 19 '21 at 19:33
  • make sure you check for app render counts. maybe you have a re-render issue that will destroy the useState value. in that case, you can apply `react memo` HOC to your app.js to prevent unwanted re-renders. – amir hosein ahmadi Jun 21 '21 at 10:31

2 Answers2

1

A state is a component's responsibility. If you want to update parent's state from child you can pass a function(defined in the parent) which will inturn update the state. You cannot pass your setState like this.

Would recommend this if you still want to keep it short:

<Login username={username} setUsername={(val)=> { setUsername(val)}} />}
Tushar Shahi
  • 16,452
  • 1
  • 18
  • 39
1

I think username is null after redirect coz you use window location, try to use history hook

const Login = (props) => {
let username = props.username;
let history = useHistory();
const [password, setPassword] = useState("");

function handleSubmit(e) {
    e.preventDefault();
    axiosInstance.post('url', {
        username: username,
        password: password
    }).then(response => {
            props.setUsername(username);
        }
    ).then(() => history.push(`/dashboard/${username}`))
        .catch(error => {
            throw error;
        });
}

return (
    <MyForm onSubmit={handleSubmit}>
        <Form.Group controlId="formBasicUser">
            <Form.Label>Username</Form.Label>
            <Form.Control type="text" name="username" value={username} placeholder="Enter username" onChange={(e) => props.setUsername(e.target.value)}/>
        </Form.Group>

        <Form.Group controlId="formBasicPassword">
            <Form.Label>Password</Form.Label>
            <Form.Control type="password" name="password" value={password} placeholder="Password" onChange={e => setPassword(e.target.value)}/>
        </Form.Group>
        <Button variant="primary" type="submit">
            Login
        </Button>
    </MyForm>
);};
  • Ok, in this case, you need to save in storage ( for ex in localStorage) user id, and then you need to make request to the server for getting current user by user id, or simply save in localStorage you uathorized user. – Ruslan Kolibabchuk Jun 21 '21 at 08:37