You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中currentMovie状态对象值无法更新问题排查

问题:React下拉菜单切换时currentMovie状态未更新

我尝试用React创建电影名称下拉菜单,希望切换选项时,通过选中值匹配movies数组中对象的id来更新currentMovie状态,但切换选项时currentMovie的值没变化,代码如下:

import { useState } from 'react';
import MovieComp from './Movie';

function ParentComp(props) {
  
const [movies, setMovies] = useState( [ { id : 1 , name : "Under the Dome", pic :
      "https://static.tvmaze.com/uploads/images/medium_portrait/81/202627.jpg" },
      { id : 2 , name : "Person of Interest", pic :
      "https://static.tvmaze.com/uploads/images/medium_portrait/163/407679.jpg" },
      { id : 3 , name : "Bitten", pic :
      "https://static.tvmaze.com/uploads/images/medium_portrait/0/15.jpg" } ] )

  const [currentMovie, setCurrentMovie] = useState( {id : "" , name : "", pic : "" } )

  function createDropMenu() {
    return movies.map( item => {
      return <option key={item.id} value={item.id} > {item.name} </option>
    } )
  }

  function updateMovie(e) {
    if (e.target.value === 0) {
      console.log("test")
      let selectedMovie = {id : "" , name : "", pic : "" };
      let selectedMovieEntries = Object.entries(selectedMovie);
      selectedMovieEntries.map( entry => {
        setCurrentMovie( prev => ( {...prev, [ entry[0] ]: entry[1] } ) );
      })
      
    } else {
      console.log("test")
      let selectedMovie = movies.find( item => item.id === e.target.value );
      let selectedMovieCopy = {};
      selectedMovieCopy = {...selectedMovie};
      let selectedMovieEntries = Object.entries(selectedMovieCopy);
      selectedMovieEntries.map( entry => {
        setCurrentMovie( prev => ( {...prev, [ entry[0] ]: entry[1] } ) );
      }) 
    }
  }

  return (
    <div>
      <h3> Pick a movie: </h3> 
      <select onChange={updateMovie}>
        <option value={0} ></option>
        {createDropMenu()}
      </select> <br/>

      <MovieComp name = {currentMovie.name} pic = {currentMovie.pic} /> 
    </div>
  );
}

export default ParentComp;

问题原因及修复方案

核心问题1:类型不匹配

select元素的value属性返回的是字符串类型,而你movies数组里的id是数字类型,所以item.id === e.target.value的比较永远不成立,无法找到对应的电影对象,自然无法更新currentMovie。

核心问题2:不必要的多次状态更新

你通过遍历对象属性多次调用setCurrentMovie,React的状态更新是批量处理的,多次调用会被合并,而且完全没必要逐个属性更新,直接一次性设置整个对象即可。

修复后的代码

import { useState } from 'react';
import MovieComp from './Movie';

function ParentComp(props) {
  
const [movies, setMovies] = useState( [ 
  { id : 1 , name : "Under the Dome", pic : "https://static.tvmaze.com/uploads/images/medium_portrait/81/202627.jpg" },
  { id : 2 , name : "Person of Interest", pic : "https://static.tvmaze.com/uploads/images/medium_portrait/163/407679.jpg" },
  { id : 3 , name : "Bitten", pic : "https://static.tvmaze.com/uploads/images/medium_portrait/0/15.jpg" } 
] )

const [currentMovie, setCurrentMovie] = useState( {id : "" , name : "", pic : "" } )

function createDropMenu() {
  return movies.map( item => {
    return <option key={item.id} value={item.id} > {item.name} </option>
  } )
}

function updateMovie(e) {
  // 将字符串类型的value转为数字
  const selectedId = Number(e.target.value);
  
  if (selectedId === 0) {
    // 直接重置整个currentMovie对象
    setCurrentMovie({ id: "", name: "", pic: "" });
  } else {
    // 现在类型匹配,能正确找到对应的电影对象
    const selectedMovie = movies.find(item => item.id === selectedId);
    // 增加判断,防止找不到对应id的情况
    if (selectedMovie) {
      // 直接设置整个对象,无需逐个属性更新
      setCurrentMovie(selectedMovie);
    }
  }
}

return (
  <div>
    <h3> Pick a movie: </h3> 
    <select onChange={updateMovie}>
      <option value={0} ></option>
      {createDropMenu()}
    </select> <br/>

    <MovieComp name={currentMovie.name} pic={currentMovie.pic} /> 
  </div>
);
}

export default ParentComp;

关键修改点

  • 使用Number()将e.target.value转为数字,确保与movies中的id类型一致,让find方法能正确匹配。
  • 移除循环遍历属性的逻辑,直接通过一次setCurrentMovie设置整个对象,避免状态更新合并问题,代码更简洁。
  • 增加if (selectedMovie)判断,提升代码健壮性,防止出现找不到对应id的异常情况。

内容的提问来源于stack exchange,提问作者krissy lynn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 11:37:58