繁体   English   中英

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

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

我有一个叫做 DiscardPile 的组件,它在你的道具(props.cards)中接收一个像这样的对象数组:

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

那么,组件 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>
        )
    }

}

'componentDidMount' 应该更新对象的 currentOrder 属性并再次渲染卡片列表,但这并没有发生。 事实上,列表被渲染为空。 我能做些什么来解决这个问题?

(对不起,我的英语不好)

--更新--

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>
        )
    }

}

首先,您不需要具有 currentCards 状态元素。 如果您需要始终使用 props 元素内容更新 state 元素,请以这种方式思考,您可能认为这是错误的。 此外,如果您的 state 元素只是您在 props 中收到的元素的轻微变化,那么您绝对不需要它。 您的代码不起作用,因为在第一次渲染时,您的组件接收到一个空数组,因此设置了一个空的 currentCards 数组并且永远不会更改它。

只需使用

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>
    )
}` 

以达到预期的行为。

如果您只想在您的 state 上拥有 props.cards 的初始版本,您可能希望使用 componentDidUpdate 甚至 shouldComponentUpdate 和一组明确定义的规则,以避免性能损害或无限重新渲染。

由于componentDidMount只运行一次,如果prop稍后发生更改,您所做的任何更改都不会生效。

道具cards最初设置为[] 因此,除非您将排序逻辑移到其他地方,否则它将永远不会更新状态以包含更新后的数组。

在不知道您想要的确切逻辑的情况下,这样的事情可能会起作用:

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});
  }
}

仅当cards数组的长度发生变化时,才会更新状态。

暂无
暂无

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

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