繁体   English   中英

setState()不更新值

[英]setState() doesn't update value

我正在尝试更新组件的状态,但无法正常工作。 我有主页容器组件=>嵌套的Navbar容器组件=>嵌套的NavItem UI组件。 同样在主页上,我有AddNavItem容器组件,应将项目添加到Navbar。 看起来像这样:

Main
|
|--NavBar
|   |
|   |--NavItem
|
|--AddNavItem

这是我的主页代码:

import React, { Component } from 'react';
import Navbar from '../nav/Navbar'
import AddNavItem from '../fields/AddNavItem'

class Main extends Component {
    state = {
        items: [
            {id: 1, name: 'Услуги', link: 'services'},
            {id: 2, name: 'Цены', link: 'prices'},
            {id: 3, name: 'Как это работает?', link: 'works'},
        ]
    }

    addNavItem = (item) => {
        this.setState((state) => {
            let newItems = [...state.items];
            newItems.unshift(item)
            console.log(newItems);
            return { 
               items: newItems
            }
        });
    }

    render() {
        return (
            <div>
                <Navbar items={ this.state.items }/>
                <AddNavItem addNavItem={ this.addNavItem }/>
            </div>
        );
    }
}

export default Main;

问题是即使在addNavItem触发后,我也总是会得到带有3个初始obj的旧数组。 <Navbar />仍然获得具有3个元素的数组。 我已经阅读了有关异步setState的信息,并按照文档https://reactjs.org/docs/faq-state.html中的说明进行了操作。

UPD:我更改了代码(取消移位)以返回数组,而不是数组的长度。 控制台日志显示我得到了4个obj的新数组

UPD:我所有组件的完整代码:

导航栏

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

class Navbar extends Component {
    state = {
        items: this.props.items,
    }

    render() {
        return (
            <div className="centered navbar grey">
                <h2>MyReact</h2>
                <ul>
                    <NavItem items={ this.state.items }/>
                </ul>
            </div>
        );
    };
}

export default Navbar;

NavItem:

import React from 'react';

const NavItem = ({ items }) => { 
    const menuItemList = items.map((item) => {
        return (
            <li key={item.id}>
                { item.name }
            </li>
        );
    })
    return (
        <div>
            { menuItemList }
        </div>
    )
}

export default NavItem;

AddNavItem:

import React, { Component } from 'react';

class AddNavItem extends Component {
    state = {
        id: Math.random(),
        name: null,
        link: null
    }

    handleInput = (e) => {
        this.setState({
            [e.target.id]: e.target.value,
        });
    }

    handleSubmit = (e) => {
        e.preventDefault();
        this.props.addNavItem(this.state);
    }

    render() {
        return (
            <div className="centered flex-column-centered">
                <form onSubmit={ this.handleSubmit }>
                    <h4 className="labelField">Название раздела:</h4>

                    <input 
                        className="inputField" 
                        type="text"
                        id="name" 
                        placeholder="укажите название" 
                        onChange={ this.handleInput } />

                    <h4 className="labelField">URL:</h4>

                    <input
                        className="inputField" 
                        type="text"
                        id="link" 
                        placeholder="укажите ссылку" 
                        onChange={ this.handleInput } />

                    <button className="submitBtn">Добавить</button>
                </form>
            </div>
        );
    }
}

export default AddNavItem;

 let arr = [3,4,5] console.log(arr.unshift(3,5)) 

addNavItem = (item) => {
    let newItems = [...this.state.items];
    newItems.unshift(item)
    this.setState({
            items: newItems
        }
    });
}

现在,您要更新数组并将元素添加到数组的开头,我认为这是您想要的,这就是您选择升档的原因。 然后将状态设置为等于您拥有的更新数组。

根据Mozilla的文档

unshift()方法将一个或多个元素添加到数组的开头,并返回数组的新长度。

因此,当您尝试使用此方法更改状态时,它会返回数组的长度,而不是您尝试将状态更新为的新数组。 最重要的是,此方法是可变的,因为您正在修改原始数组,而不是返回它的新副本。 我建议您更改代码以使用array.prototype.concat()方法代替,因为它可以使您的状态保持不变,因为它返回新数组而不是修改原始数组。

尝试将您的方法更改为此。

addNavItem = (item) => {
    this.setState({ items: this.state.items.concat(item) });
}

编辑:

如果使用的是es6,则可以使用传播语法 ,该语法还返回数组的新副本。

addNavItem = (item) => {
    this.setState({ items: [...this.state.items, item] });
}

编辑2:在Navbar组件中,您将this.props.items设置为在初始化时声明,然后在this.props.items更改时不更新状态。

您不需要此组件的状态,我可以将NavBar组件更改为如下所示:

import React from 'react';
import NavItem from './NavItem';

const Navbar = (props) => {
        return (
            <div className="centered navbar grey">
                <h2>MyReact</h2>
                <ul>
                    <NavItem items={ props.items }/>
                </ul>
            </div>
        );
}

export default Navbar;

编辑3:

如果要将项目保持在NavBar组件中的内部状态,则需要注意是否对该组件上的item道具进行了更新。

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

class Navbar extends Component {
    state = {
        items: this.props.items,
    }

    componentDidUpdate(prevProps) {
      if (this.props.items!== prevProps.items) {
        this.setState({ items: this.props.items });
      }
    }

    render() {
        return (
            <div className="centered navbar grey">
                <h2>MyReact</h2>
                <ul>
                    <NavItem items={ this.state.items }/>
                </ul>
            </div>
        );
    };
}

export default Navbar;
addNavItem = (item) => {
  this.setState((prevState) => {items: [...prevState.items, item]})
}

这应该工作。

暂无
暂无

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

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