首页 > 解决方案 > React hook useState 没有正确映射数组对象

问题描述

我有一个将对象数组传递给另一个 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)中的原始 3 个对象。movieList

标签: reactjstypescriptreact-hooks

解决方案


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

每次调用它时,您都会重置回存储在 中的任何内容movieList,再加上一部额外的电影。因此,由于您连续执行了 3 次,因此您最终得到了原始列表以及最后一部电影。

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

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

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

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

推荐阅读