反应挂钩useState未正确映射数组对象

时间:2020-07-28 13:58:58

标签: reactjs typescript react-hooks

我有一个将对象数组传递给另一个React功能组件的表单:

    import React, { useState } from 'react'
    import uuid from 'uuid/v1';

    const NewMovieForm = ( {addMovie }) => {
        const movies = [
            {title: 'Generic Action Movie', director: 'Some Guy', id: uuid()},
            {title: 'Jumpscare Horror Flick', director: 'Some Guy', id: uuid()},
            {title: 'Romantic Comedy Drama', director: 'Some Guy', id: uuid()},
        ]
        const handleSubmit = (e) => {
            e.preventDefault();
            addMovie(movies);
        }
        return (
            <form onSubmit={handleSubmit}>
                <input type="submit" value="add movie" />
            </form>
        )
    }

    export default NewMovieForm

其他功能组件:

const SearchAPIResults = () => {
  const [movieList, setMovies] = useState([
    { title: 'Weird Space Movie', director: 'Some Guy', id: 1},
    { title: 'Random Comedy', director: 'Some Guy',id: 2},
    { title: 'Thriller With Nick Cage', director: 'Some Guy',id: 3}
  ])
  const addMovie = (movies) => {
    movies.forEach(movie => {
      console.log(movie)
      setMovies([...movieList, {title: movie.title, director: movie.director, id: movie.id}])
      console.log(movieList)
    })

  }
  return (
    <div>
      <ul>
        {movieList.map(movie => {
          return (<li key={movie.id}>{movie.title}</li>)
        })}
      </ul>
      <NewMovieForm addMovie={addMovie} />
    </div>
  )
}

export default SearchAPIResults;

当我按下submit组件中的NewMovieForm按钮时,只有{title: 'Romantic Comedy Drama', director: 'Some Guy', id: uuid()},对象被添加到浏览器中显示的电影列表中。 console.log(movie);输出正确的电影对象,而console.log(movieList)输出movieList数组中的原始3个对象。

1 个答案:

答案 0 :(得分:2)

setMovies([...movieList, {title: movie.title, director: movie.director, id: movie.id}])

每次调用时,您都将重置为movieList中存储的内容,再加上一部额外的电影。因此,由于您连续进行了三次,因此最终得到的是原始列表以及最后一部电影。

如果需要基于旧状态创建新状态,则应使用setMovies的回调版本。这样可以确保您始终使用最新版本:

setMovies(previous => [...previous, {title: movie.title, director: movie.director, id: movie.id}])

不过,在您的情况下,我会摆脱对setMovies的多次调用,而只需要一个:

const addMovie = (movies => {
  setMovies(previous => [...previous, ...movies]);
}