[英]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.