Home > Net >  How to update state of parent component with a lifted up props?
How to update state of parent component with a lifted up props?

Time:11-08

I have a problem with updating the state of parent component with a props from child component. It seems the following code is not working, however it looks fine

setUsersList(prevState => {
            return [...prevState, data];
        });

My parent component receives an object. Console.log(data) outputs the object received from child component. However, when console logging updated state (console.log(usersList)) it returns an empty array

Parent component:

import React, { useState } from "react";
import AddUser from "./components/Users/AddUser";
import UsersList from "./components/Users/UsersList";

function App() {
    const [usersList, setUsersList] = useState([]);

    const addUserHandler = data => {
        console.log(data);
        setUsersList(prevState => {
            return [...prevState, data];
        });
        console.log(usersList);
    };

    return (
        <div>
            <AddUser onAddUser={addUserHandler}></AddUser>
            <UsersList users={usersList}></UsersList>
        </div>
    );
}

export default App;

Child component:

import React, { useState } from "react";
import Button from "../UI/Button";
import Card from "../UI/Card";
import styles from "./AddUser.module.css";

const AddUser = props => {
    const [inputData, setInputData] = useState({ name: "", age: "" });

    const addUserHandler = event => {
        event.preventDefault();

        if (
            inputData.age.trim().length === 0 ||
            inputData.name.trim().length === 0
        ) {
            return;
        }

        if ( inputData.age < 1) {
            return;
        }

        props.onAddUser(inputData);
        console.log(inputData.name, inputData.age);

        setInputData({ name: "", age: "" });
    };

    const usernameChangeHandler = event => {
        setInputData({ ...inputData, name: event.target.value });
    };

    const ageChangeHandler = event => {
        setInputData({ ...inputData, age: event.target.value });
    };

    return (
        <Card className={styles.input}>
            <form onSubmit={addUserHandler}>
                <label htmlFor="username">Username</label>
                <input
                    id="username"
                    type="text"
                    onChange={usernameChangeHandler}
                    value={inputData.name}
                ></input>
                <label htmlFor="age">Age (Years)</label>
                <input
                    id="age"
                    type="number"
                    onChange={ageChangeHandler}
                    value={inputData.age}
                ></input>
                <Button type="submit">Add User</Button>
            </form>
        </Card>
    );
};

export default AddUser;

CodePudding user response:

Due to the way react re-renders components, your console may not log with the expected state change. Instead you can use useEffect for debugging purposes:

parent component

useEffect(() => {
  console.log("usersList", usersList);
}, [usersList])

alternatively, having a console.log statement in the body of your functional component should log the correct 'usersList'.

const [usersList, setUsersList] = useState([]);
console.log("usersList", usersList);

CodePudding user response:

The state variable won't change right away when you call setState function from the useState hook. Since it is an asynchronous event.

So you might need to write your code like this to see the right console.log

const addUserHandler = data => {
  console.log(data);
  setUsersList(prevState => {
    const temp = [...prevState, data];
    console.log(temp); // like this
    return temp;
  });
};

If the state is not updating in the UI. Please paste the error or the warning message.

CodePudding user response:

Since setUserList is async function, you can not see the changes on console in the addUserHandler function.

function App() {
    const [usersList, setUsersList] = useState([]);

    const addUserHandler = data => {
        console.log(data);
        setUsersList(prevState => {
            return [...prevState, data];
        });
    };
    console.log(usersList);

    return (
        <div>
            <AddUser onAddUser={addUserHandler}></AddUser>
            <UsersList users={usersList}></UsersList>
        </div>
    );
}

export default App;

This will work. Thanks.

  • Related