setState没有正确更新状态 [英] setState is not updating state properly

查看:74
本文介绍了setState没有正确更新状态的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

抱歉,我真的很想念React中子组件的 props 中传输

Sorry, I really miss something with the transmission of state within props of sub components in React.

我已经实现了一个包含3个组件的待办事项列表版本。

I have implemented a version of a todo list with 3 components.

有一个表单组件和 ListTodo 组件。状态仅存储在 App 组件中。

There is a Form component and a ListTodo component. The state is stored only in the App component.

import React, {Component} from 'react';
import './App.css';

class App extends Component {

    constructor(props) {
        super(props);
        this.state = {
            tasks: ["un truc", "autre truc"]
        };
        this.addTask = this.addTask.bind(this);
    }

    addTask(task) {
        this.setState({
            tasks: this.state.tasks.push(task)
        })
    }

    render() {
        return (
            <div className="App">
                <Form onTaskAdded={ this.addTask }></Form>
                <ListTodo tasks={ this.state.tasks }></ListTodo>
            </div>
        );
    }
}

class Form extends Component {

    constructor(props) {
        super(props);
        this.state = {
            task: ""
        }

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

    handleChange(event) {
        this.setState({
            task: event.target.value
        });
    }

    addTask(event) {
        this.props.onTaskAdded(this.state.task);
        event.preventDefault();
    }

    render() {
        return (
            <form onSubmit={ this.addTask }>
                <input placeholder="À faire" onChange={ this.handleChange }></input>
                <input type="submit"></input>
            </form>
        )
    }
}

class ListTodo extends Component {

    render() {
        const tasks = this.props.tasks.map((t, i) => (
                <li key={i}>{t}</li>
            ))

        return (
            <ul>{tasks}</ul>
        )
    }
}

export default App;

显示效果良好,所以 ListTodo 实现看到道具任务。但是在提交表单后,我在 ListTodo.render 上收到错误:

The display is good at start so the ListTodo achieves to see the prop tasks. But after a form submission, I get an error on ListTodo.render :


TypeError:this.props.tasks.map不是函数

TypeError: this.props.tasks.map is not a function

当我在console.log中时,这个。 props.tasks ,我没有得到我的数组但是数组的长度。

When I console.log the this.props.tasks, I don't get my array but the length of the array.

你知道为什么吗?

编辑
感谢您的回答,你说得对。我错过了Array.push的行为。

Edit : Thanks for answers guys, you're right. I missed the behavior of Array.push.

但是React似乎仍然很奇怪。如果我让错误的代码
this.setState({
tasks:this.state.tasks.push(task)
})

But React seems still odd. If I let the mistaken code this.setState({ tasks: this.state.tasks.push(task) })

然后一个 console.log(JSON.stringify(this.state))显示:

{tasks:[un truc,autre truc,aze]}

非常令人不安,无法信任console.log ...

Very disturbing to not be able to trust a console.log...

推荐答案

根据 MDN DOC


push()方法将一个或多个元素添加到数组的末尾并且
返回数组的新长度

Array.push 永远不会返回结果数组,它会返回数字,所以在添加第一个任务后, this.state.tasks 变成一个数字,当你试图在数字上运行地图时它会抛出错误。

Array.push never returns the result array, it returns the number, so after adding the first task, this.state.tasks becomes a number, and it is throwing the error when you trying to run map on number.

你在这里犯了错误:

addTask(task) {
    this.setState({
        tasks: this.state.tasks.push(task)
    })
}

这样写:

addTask(task) {
    this.setState( prevState => ({
        tasks: [...prevState.tasks, task]
    }))
}

这里的另一个重要的事情是,新状态将取决于之前的状态值,所以不要在setState内使用 this.state ,使用更新程序功能。

Another import thing here is, the new state will be depend on the previous state value, so instead of using this.state inside setState, use updater function.

关于编辑部分的说明:

两个重要的事情是发生在那里:

Two important things are happening there:

1 - setState是异步的,因此在setState之后我们可以期待更新的状态值。

1- setState is async so just after setState we can expect the updated state value.

检查此项以获取有关 setState的异步行为

Check this for more details about async behaviour of setState.

2 - Array.push始终改变原始状态通过将项目推入该数组,所以你通过 this.state.tasks.push()直接改变状态值。

2- Array.push always mutate the original array by pushing the item into that, so you are directly mutating the state value by this.state.tasks.push().

检查 DOC ,了解有关setState的更多详细信息。

Check the DOC for more details about setState.

检查 传播运营商(...)的Spread_operatorrel =nofollow noreferrer> MDN Doc

Check the MDN Doc for spread operator (...).

检查此代码段:

let a = [1,2,3,4];

let b = a.push(5);  //it will be a number

console.log('a = ', a);

console.log('b = ', b);

这篇关于setState没有正确更新状态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆