简体   繁体   中英

React hook - setState didn't update state

Solved

Seem like in react hook, no matter how many setState you call within a triggered function. Only the last setState will be processed. Thus react ignored all above setState calls.

It was not the case in react class component.

Really unexpected react hook behavior that I haven't known before.


Let's say, I have 2 files with object type like this {name: 'something', data: 123}.

I render for each file 2 radio inputs to select

          type1   type2
file_1    radio   radio
file_2    radio   radio

What I want is that:

  • 1 file can not be both type1 and type2.
  • Each type has max 1 file, meaning file_1 and file_2 can not be type1 (or type2) at the same time.

In short words, each row only 1 can be selected, same for each column.

And I got 2 problems:

  1. If I use onChange in radio input, once radio is selected, it can not be deselected. After I changed to onClick and this solved problem.
  2. file_1 (or file_2) can be both type1 and type2 at the same time, which is not what I want.

Here is the code:

const files = [{name: 'file_1', data:1243}, {name: 'file_2', data: 2323}]
function App() {
  const [state, setState] = useState({type1: null, type2: null})

  const handleType1 = (obj) => () => {
    if ((state.type2 || {name: ''}).name === obj.name) {
      setState({...state, type2: null}) // <===================== this setState didn't update state
    }

    if((state.type1 || {name: ''}).name === obj.name) {
      setState({...state, type1: null})
    } else {
      setState({...state, type1: obj})
    }
  }

  const handleType2 = (obj) => () => {
    if ((state.type1 || { name: '' }).name === obj.name) {
      setState({...state, type1: null});  // <================== this setState didn't update state
    }

    if ((state.type2 || { name: '' }).name === obj.name) {
      setState({ ...state, type2: null });
    } else {
      setState({ ...state, type2: obj });
    }
  }
  return (
    <div className="App">
      <span>.......</span>
      <span> t1</span> 
      <span> t2</span>
      {
        files.map(file => {
        return (
          <div key={file.name}>
            <span>{file.name}</span>
            <input type='radio' checked={(state.type1 || { name: '' }).name === file.name} onClick={handleType1(file)}/>
            <input type='radio' checked={(state.type2 || { name: '' }).name === file.name} onClick={handleType2(file)}/>
          </div>)    
        })
      }    
    </div>
  );
}

Link to codesandbox

Any ideas, why it didn't work as intended? Thanks for any helps.

Can I suggest you start by simplifying this down first like this: https://codesandbox.io/s/elastic-sun-n7q0l?fontsize=14

When you click on the radio buttons now you will see in the console that it returns the file name and the value that you want for the radio, eg. "file__1, type1"

I'm not sure this is exactly what you are asking but it seems more of a logical starting point rather than all the state code that you had in there?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM