0

I have a problem with my useState() in ReactJs. I want to set up my variable but my console.log return me nothing :

const [selectedMinister, setSelectedMinister] = useState("");

const handleChange = (event) => {
    console.log(event.target)
    let selectM = event.currentTarget.getAttribute("data-minister_name");
    setSelectedMinister(selectM);
    console.log(selectedMinister);

};


<List dense sx={{ width: '100%', maxWidth: 360, bgcolor: 'background.paper' }}>
    {listMiniters.map((c) => (
        <ListItem
            key={c.label}
            disablePadding
            onClick={handleChange}
            data-minister_name={c.label}
        >
            {/* my code */}
    ))}
</List>

Do you have some idea where does the problem come from ?

Renjus
  • 242
  • 1
  • 3
  • 15
  • State updates are asynchronous. The value you want to log there is `selectM`, not `selectedMinister`. – David Feb 24 '22 at 15:28

2 Answers2

2
setSelectedMinister(selectM); 

is an async operation. You may want to log your state in useEffect which is getting called when your state changes (if you put your state in the dependecy array)

useEffect(()=>{
console.log(selectedMinister);
},[selectedMinister])
MWO
  • 2,627
  • 2
  • 10
  • 25
1

The state change will only be reflected on the next render event (aka after your handleChange function runs and React decides to re-run the function component's body. Until then, you have access to selectM so there's no added benefit of getting the state from the setState function if you only need it in the context of that function:

const handleChange = (event) => {
    console.log(event.target)
    let selectM = event.currentTarget.getAttribute("data-minister_name");
    setSelectedMinister(selectM);
    // console.log(selectedMinister);
    console.log(selectM) => it will be fine.
};

The state change will take place soon, the question is what you really need to mutate the state for because so far it doesn't seem necessary to set state at all.

I predict that you want to maybe have something like:

<div>{selectedMinister}</div>

In your render function: this will work or if you need to make an API request within that handleChange function you can do that as well:

const [selectedMinister, setSelectedMinister] = useState("");
const [ministerBio, setMinisterBio] = useState();

const handleChange = async (event) => {
    console.log(event.target)
    let selectM = event.currentTarget.getAttribute("data-minister_name");
    setSelectedMinister(selectM);
    const res = await fetch(`/api/ministers?name=${selectM}`)
    const json = await res.json();
    setMinisterBio(json);
};

If you really want to specifically console.log the selectedMinister name that comes directly from state you can useEffect as suggested by the other answer (by MWO) or if you use the old school this.setState(selectedMinister) you can use the callback within that method: this.setState(selectedMinister, console.log). In react setting the newState does not immediately run, it will be there on the next render.

Zargold
  • 1,892
  • 18
  • 24