簡體   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