简体   繁体   English

“componentDidMount”生命周期方法不更新状态

[英]The 'componentDidMount' lifecycle method does not update the state

I have a component called DiscardPile that's receive in your props (props.cards) an array of objects like this:我有一个叫做 DiscardPile 的组件,它在你的道具(props.cards)中接收一个像这样的对象数组:

{key: 'key', 'type', suit: 'suit', label: 'label', flipped: 'fliped, draggable: 'draggable', currentOrder: 0}

Well, the component DiscardPile is shown bellow:那么,组件 DiscardPile 如下所示:

import React, { Component } from 'react';
import $ from 'jquery';
import 'jquery-ui/ui/core';
import 'jquery-ui/ui/widgets/droppable';

import './DiscardPile.scss';

import Card from '../Card/Card';
export default class DiscardPile extends Component {

    constructor(props) {
        super(props);
        this.state = {
            currentCards: []        
        }
    }

    componentDidMount() {
        let currentCards = [...this.props.cards];
        for(let i = 0; i < currentCards.length; i++) {
            currentCards[i].currentOrder = i;
        }
        this.setState({currentCards: currentCards});
    }

    render() {
        return (
            <div id="discard-pile" className="discard-pile">
                {this.state.currentCards.map(card =>(
                    <Card key={card.key} type={card.type} suit={card.suit} label={card.label} flipped={card.flipped} draggable={card.draggable} currentOrder={card.currentOrder}></Card>
                ))}
            </div>
        )
    }

}

The 'componentDidMount' should update the currentOrder attribute of the object and render the cards list again, but this is not happening. 'componentDidMount' 应该更新对象的 currentOrder 属性并再次渲染卡片列表,但这并没有发生。 In fact, the list being rendered empty.事实上,列表被渲染为空。 What could I do to fix this?我能做些什么来解决这个问题?

(Sorry for my bad english) (对不起,我的英语不好)

-- UPDATE -- --更新--

The DiscardPile component is called by the KlondikeTable component, shown bellow: DiscardPile 组件由 KlondikeTable 组件调用,如下所示:

import React, { Component } from 'react';

import './KlondikeTable.scss';

import Card from './../../generalComponents/Card/Card';
import DiscardPile from '../../generalComponents/DiscardPile/DiscardPile';
import FlippedPile from '../../generalComponents/FlippedPile/FlippedPile';
import SuitsPile from '../../generalComponents/SuitsPile/SuitsPile';
import CardsColumn from '../../generalComponents/CardsColumn/CardsColumn';

export default class KlondikeTable extends Component {

    constructor(props) {
        super(props);
        this.state = {
            cards: [],
            initialDistribution: {
                discardPile: [],
                flippedPile: [],
                cardsPile1: [],
                cardsPile2: [],
                cardsPile3: [],
                cardsPile4: [],
                cardsPile5: [],
                cardsPile6: [],
                cardsPile7: [],
            },
            currentDistribution: null
        }
        this.generateCards = this.generateCards.bind(this);
        this.shuffleCards = this.shuffleCards.bind(this);
    }

    componentDidMount() {
        this.generateCards();
    }

    generateCards() {
        let cards = [];
        let types = ["K","Q","J","10","9","8","7","6","5","4","3","2","A"];
        let suits = ["spades", "clubs", "diamonds", "hearts"];
        for(let i = 0; i < suits.length; i++) {
            for(let j = 0; j < types.length; j++) {
                cards.push(
                    {key: types[j] + "-" + suits[i] + "-0", type: types[j], suit: suits[i], label: "0", flipped: false, draggable: true, currentOrder: 0}
                )
            }
        }
        this.setState(state => ({...state, cards: cards}), () => {
            this.shuffleCards();
        });
    }

    shuffleCards() {
        let amount = 52;
        let numbersArray = [];
        let cards = [...this.state.cards];
        let initialDistribution = {...this.state.initialDistribution};
        for(let i = 0; i < 52; i++) {
            numbersArray.push(i);
        }
        for(let i = 0; i < 24; i++) {
            let randomNumber = Math.floor(Math.random() * amount);
            let removedElement = cards.splice(randomNumber, 1)[0];
            initialDistribution.discardPile.push(removedElement);
            amount--;
        }
        for(let i = 0; i < 28; i++) {
            let randomNumber = Math.floor(Math.random() * amount);
            let removedElement = cards.splice(randomNumber, 1)[0];
            if(i < 1) {
                initialDistribution.cardsPile1.push(removedElement);
            }else if(i < 3) {
                initialDistribution.cardsPile2.push(removedElement);
            }else if(i < 6) {
                initialDistribution.cardsPile3.push(removedElement);
            }else if(i < 10) {
                initialDistribution.cardsPile4.push(removedElement);
            }else if(i < 15) {
                initialDistribution.cardsPile5.push(removedElement);
            }else if(i < 21) {
                initialDistribution.cardsPile6.push(removedElement);
            }else if(i >= 21) {
                initialDistribution.cardsPile7.push(removedElement);
            }
            amount--;
        }
        this.setState({initialDistribution: initialDistribution, currentDistribution: initialDistribution});
    }

    render() {
        return (
            <div className="klondike-table">
                <DiscardPile cards={this.state.initialDistribution.discardPile}></DiscardPile>
                <FlippedPile cards={this.state.initialDistribution.flippedPile}></FlippedPile>
                <div className="suits-piles-container">
                    <SuitsPile></SuitsPile>
                    <SuitsPile></SuitsPile>
                    <SuitsPile></SuitsPile>
                    <SuitsPile></SuitsPile>
                </div>
                <CardsColumn cards={this.state.initialDistribution.cardsPile1}></CardsColumn>
                <CardsColumn cards={this.state.initialDistribution.cardsPile2}></CardsColumn>
                <CardsColumn cards={this.state.initialDistribution.cardsPile3}></CardsColumn>
                <CardsColumn cards={this.state.initialDistribution.cardsPile4}></CardsColumn>
                <CardsColumn cards={this.state.initialDistribution.cardsPile5}></CardsColumn>
                <CardsColumn cards={this.state.initialDistribution.cardsPile6}></CardsColumn>
                <CardsColumn cards={this.state.initialDistribution.cardsPile7}></CardsColumn>                
            </div>
        )
    }

}

First of all, you do not need to have a currentCards state element.首先,您不需要具有 currentCards 状态元素。 Think of it this way if you need your state element to be always updated with your props element content you might be thinking it wrong.如果您需要始终使用 props 元素内容更新 state 元素,请以这种方式思考,您可能认为这是错误的。 Moreover, if your state element is just going to be a slight variation of the element you are receiving in props then you definitely don't need it.此外,如果您的 state 元素只是您在 props 中收到的元素的轻微变化,那么您绝对不需要它。 Your code isn't working because on the first render your component is receiving an empty array, thus setting an empty currentCards array and never changing it.您的代码不起作用,因为在第一次渲染时,您的组件接收到一个空数组,因此设置了一个空的 currentCards 数组并且永远不会更改它。

Just use只需使用

render() {
    return (
        <div id="discard-pile" className="discard-pile">
            {this.props.cards.map((card, currentOrder)=>(
                <Card key={card.key} type={card.type} suit={card.suit} label={card.label} flipped={card.flipped} draggable={card.draggable} currentOrder={currentOrder}></Card>
            ))}
        </div>
    )
}` 

to achieve the expected behavior.以达到预期的行为。

If what you want is to have only the initial version of props.cards on your state you might want to use componentDidUpdate or even shouldComponentUpdate with a well defined set of rules to avoid performance damage or infinitely re-rendering.如果您只想在您的 state 上拥有 props.cards 的初始版本,您可能希望使用 componentDidUpdate 甚至 shouldComponentUpdate 和一组明确定义的规则,以避免性能损害或无限重新渲染。

Since componentDidMount only runs once, any changes you're making will not take effect if the prop changes later on.由于componentDidMount只运行一次,如果prop稍后发生更改,您所做的任何更改都不会生效。

The prop cards is initially set to [] .道具cards最初设置为[] So unless you move your ordering logic somewhere else, it will never be updated in state to contain your updated array.因此,除非您将排序逻辑移到其他地方,否则它将永远不会更新状态以包含更新后的数组。

Without knowing the exact logic you want, something like this may work:在不知道您想要的确切逻辑的情况下,这样的事情可能会起作用:

componentDidUpdate(prevProps) {
  if (prevProps.cards.length !== this.props.cards.length) {
    let currentCards = [...this.props.cards];
    for(let i = 0; i < currentCards.length; i++) {
      currentCards[i].currentOrder = i;
    }
    this.setState({currentCards: currentCards});
  }
}

This will update the state only if the length of the cards array changes.仅当cards数组的长度发生变化时,才会更新状态。

暂无
暂无

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

相关问题 ComponentDidMount 之外的状态似乎没有更新 - State outside of ComponentDidMount does not appear to update 模拟componentDidMount生命周期方法进行测试 - Mock componentDidMount lifecycle method for testing ComponentDidMount 本地状态更新 - ComponentDidMount local state update componentDidMount生命周期方法中的条件异步动作不断循环 - conditional async actions in componentDidMount lifecycle method keeps going on a loop 我应该使用什么生命周期方法来监听 state 的变化并在反应 class 组件中相应地更新其他 state - What lifecycle method should i use to listen for changes in state and update other state accordingly in react class component 我想测试是否在生命周期方法 componentDidMount 中调用了某个方法,但出现错误 - I want to test whether a method is called within the lifecycle method componentDidMount, but I am getting an error 使用Ref实现ComponentDidMount LifeCycle事件 - React ComponentDidMount LifeCycle Event With Ref 如何在异步componentDidMount axios调用中测试正确的状态更新? - How to test correct state update in async componentDidMount axios call? 如何从componentDidMount()(不是componentDidUpdate())更新DOM中的状态对象? - How to update a state object in the DOM from componentDidMount() (not componentDidUpdate())? 在React JS componentDidMount生命周期方法中调用的警报在初始渲染之前而不是之后弹出 - Alert invoked in React JS componentDidMount lifecycle method pops up before the initial render instead of after
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM