Как повторно обработать реагирующий компонент при отображении состояния, которое является массивом объектов - PullRequest
1 голос
/ 29 сентября 2019

Я пытаюсь отобразить массив объектов в состоянии, условно возвращая один из двух реагирующих компонентов из этого состояния.Затем я изменяю это состояние в какой-то момент и ожидаю, что компонент будет повторно отображаться при изменении состояния объекта.Я понимаю, что моя проблема связана с тем, что React не распознает изменения в diff, но я не уверен, почему и какой шаблон мне нужно изменить, чтобы это работало.

Вот кодекс: https://codepen.io/steven-harlow/pen/KKPLXRO

И код из него:

const App = (props) => {
  const [todos, setTodos] = React.useState([
    {name: 'A', done: false},
    {name: 'B', done: false},
    {name: 'C', done: false},
  ])

  React.useEffect(() => {

  }, [todos])

  const handleClick = (name) => {
    const index = todos.find(todo => todo.name == name)
    let tempTodos = todos;
    tempTodos[index].done = true;
    setTodos(tempTodos);
  }

  return (
    <div>
      <h1>Hello, world!</h1>
      <div>
        {todos.map(todo => {
          return todo.done ? (<div key={'done' + todo.name}>{todo.name} : done</div>) : (<div onClick={() => handleClick(todo.name)} key={'notdone' + todo.name}>{todo.name} : not done</div>)
        })}
      </div>
    </div>
  )
}

Ответы [ 2 ]

3 голосов
/ 29 сентября 2019

Вот, пожалуйста, это здесь должно работать для вас сейчас.Я добавил туда несколько заметок.

const App = (props) => {
  const [todos, setTodos] = React.useState([
    {name: 'A', done: false},
    {name: 'B', done: false},
    {name: 'C', done: false},
  ])

  const handleClick = (name) => {
    /*
      Here you were using todos.find which was returning the object. I switched
      over to todos.findIndex to give you the index in the todos array. 
    */
    const index = todos.findIndex(todo => todo.name === name)
    /*
      In your code you are just setting tempTodos equal to todos. This isn't
      making a copy of the original array but rather a reference. In order to create 
      a copy I am adding the .slice() at the end. This will create a copy.
      This one used to get me all of the time.
    */
    let tempTodos = todos.slice();
    tempTodos[index].done = true;
    setTodos(tempTodos);
  }
  console.log(todos)
  return (
    <div>
      <h1>Hello, world!</h1>
      <div>
        {todos.map((todo,index) => {
        return todo.done ? (<div key={index}>{todo.name} : done</div>) : (<div onClick={() => handleClick(todo.name)} key={index}>{todo.name} : not done</div>)
        })}
      </div>
    </div>
  )
}


ReactDOM.render(
  <App />,
  document.getElementById('root')
);

Еще одна вещь, которую я сделал, - это упростить ключи для элементов div, созданных картой.Я просто добавил индекс на карту и использовал его для ключа, так намного чище.

Надеюсь, это поможет!

0 голосов
/ 29 сентября 2019

React не увидит состояние как , измененное , если вы не создадите новый массив.

const handleClick = n => setTodos(todos.map(t => t.name === n ? {...t, done: true} : t));
...