繁体   English   中英

React.js setState 问题

[英]React.js setState issue

我正在学习React.js ,但遇到一个非常奇怪的问题。 我一步一步地按照教程进行操作,当我调用this.setState来更新this.state object 中的笑话数组时,修改后的数组不会改变。 我想在单击复选框时将completed的属性切换为true / false 没有控制台错误。

欢迎任何意见。

JokesTemplate.js

function JokeTemplate(props){

    return (
      <div className="col-md-4">
        <label>Joke {props.item.id}</label>
        <p>Question {props.item.desc}</p>
        <p>Answer: {props.item.ans}</p>
        <input type="checkbox" checked={props.item.completed} onChange={() => props.handleChange(props.item.id)} />
      </div>
    );
}

export default JokeTemplate;

笑话.js

import React from 'react';

import JokeTemplate from './JokeTemplate';

const jokes = [{
    id:1,
    desc: "Question 1",
    ans: "Answer 1",
    completed: false
},
{
    id:2,
    desc: "Question 2",
    ans: "Answer 2",
    completed: true
},
{
    id:3,
    desc: "Question 3",
    ans: "Answer 3",
    completed: false
}];

class Jokes extends React.Component{
    constructor(){
      super()
      this.state = {
          jokesLst: jokes
      }

      this.handleChange = this.handleChange.bind(this);
    }

    handleChange(id){

       this.setState(prevState => {
           let updatedObj = prevState.jokesLst.map( item =>{
               if(item.id === id){ 
                   item.completed = !item.completed;
               }
               return item;
           })
           
           return { jokesLst: updatedObj }
       });

    }

    render(){

        const jokesComponentArr = this.state.jokesLst.map( joke => <JokeTemplate key={joke.id} item={joke} handleChange={this.handleChange} />);

        return (
            <>
              {jokesComponentArr}
            </>
        )
    }
    
}

export default Jokes;

应用程序.js

import React from 'react';
import logo from './logo.svg';
import './App.css';

import NavBar from './components/NavBar';
import Jokes from './components/Jokes';

function App() {
  
  return (
   <div className="App">
      <NavBar />
      <header className="App-header">
        <Jokes />
      </header>
    </div>
  );
}

export default App;

提前致谢。

您的代码似乎仍在修改数组中的原始元素,因为它们是未按值引用的对象。 要消除此问题,您需要在prevState的回调中复制.map()调用中的每个元素。

handleChange ,您可以尝试以下操作:

this.setState(prevState => {
    let updatedObj = prevState.jokesLst.map(item => {
        const newItem = { ...item }

        if (newItem.id === id) {
           newItem.completed = !newItem .completed
        }

        return newItem
    })
          
    return { jokesLst: updatedObj }
})

查看上面额外的const newItem = {...item }行的区别。

或者你可以使用更短的时间:

this.setState(prevState => ({
   ...prevState,
   jokesLst: prevState.jokesLst.map(item => ({
      ...item,
      completed: item.id === id ? !item.completed : item.completed
   }))
})

我认为您需要修改的只是 Jokes.js 中的 handleChange() 方法

我从未见过这种将逻辑用于过滤“项目”并在 this.setState() 方法内修改其“已完成”字段的方法。 但我建议你这样做。 所以在这里我们创建了一个新的 updatedObj 实例,执行所有操作已完成字段的逻辑。 最后只需调用 setState 并将 updatedObj 直接传递给它。 我在 codesandbox 上测试了这个,它可以工作。

handleChange(id) {
   let updatedObj = this.state.jokesLst.map((item) => {
      if (item.id === id) {
        item.completed = !item.completed;
      }
    
      return item;
    });
    
    this.setState({
      jokesLst: updatedObj
    });
   };

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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