繁体   English   中英

我应该如何从道具实例化我的状态?

[英]How should I instantiate my state from props?

左右 ,我看到从getInitialState()/构造道具初始化状态可以是一个反模式。

从道具初始化状​​态并设法保持一致的最佳方法是什么?

如您在下面看到的,我正在尝试初始化我的“ Card”组件,以便可以初始化一个likeCountisLikedByMe状态。 我这样做是为了让我可以显示一个自定义的“喜欢”计数器,并可以通过重置状态来更改“喜欢”按钮的文本。

在这一点上,我正在构造函数中执行此操作,但这是错误的方法。 我应该如何处理?

import * as React from "react";
import { CardLikeButton } from "./buttons";

export enum CardType {
    None = 0,
    Text,
    Image
}

export interface CardMedia {
    text?: string;
    imageUrl?: string;
}

export interface CardDetails {
    isLikedByMe: boolean;
    likeCount: number;
}


export interface CardParams extends React.Props<any> {
    cardType: number;
    cardId: string;
    cardMedia: CardMedia;
    cardDetails: CardDetails;
}

export class Card extends React.Component<CardParams, CardDetails> {

    state: CardDetails;

    constructor(props: CardParams) {
        super(props);

        console.log("in card constructor");
        console.log("card type: " + props.cardType);

        this.state = { // setting state from props in getInitialState is not good practice
            isLikedByMe: props.cardDetails.isLikedByMe,
            likeCount: props.cardDetails.likeCount
        };

    }

    componentWillReceiveProps(nextProps: CardParams) {
        this.setState({
            isLikedByMe: nextProps.cardDetails.isLikedByMe,
            likeCount: nextProps.cardDetails.likeCount
        });
    }

    render() {
        console.log("RENDERING CARD");
        // console.dir(this.props.cardDetails);
        // console.dir(this.props.cardMedia);
        // console.dir(this.props.cardType);

        if (this.props.cardType === CardType.Text) { // status card
            return (
                <div className="general-card">
                    <p>Text card.ID: {this.props.cardId}</p>
                    <p>{this.props.cardMedia.text}</p>
                    <CardLikeButton onButClick={this.likeButtonClicked} buttonText={this.state.isLikedByMe ? "Liked" : "Like"} isPressed={this.state.isLikedByMe}/>
                    <p>Like count: {this.state.likeCount}</p>
                </div>
            );
        } else { //photo card
            return (
                <div className="general-card">
                    <p>Image card.ID: {this.props.cardId}</p>
                    <p> {this.props.cardMedia.text} </p>
                    <img src={this.props.cardMedia.imageUrl} />
                    <br/>
                    <CardLikeButton onButClick={this.likeButtonClicked} buttonText={this.state.isLikedByMe ? "Liked" : "Like"} isPressed={this.state.isLikedByMe}/>
                    <p>Like count: {this.state.likeCount}</p>

                </div>
            );
        }
    }

    likeButtonClicked = () => {
        console.log('in card => like button clicked!');
        var _isLikedByMe = this.state.isLikedByMe;
        var _likeCount = this.state.likeCount;

        if (_isLikedByMe) {
            _likeCount--;
        } else {
            _likeCount++;
        }
        _isLikedByMe = !_isLikedByMe;

        this.setState({
            isLikedByMe: _isLikedByMe,
            likeCount: _likeCount
        })
    }
}

这是主要的列表组件:

/// <reference path="../../typings/index.d.ts" />

import * as React from "react";
import * as ReactDOM from "react-dom";

import {Card} from "./card";

import {CardParams, CardType, CardMedia, CardDetails} from "./card";

var card1: CardParams = {
    cardType: CardType.Image,
    cardId: "card1234",
    cardDetails: {
        isLikedByMe: false,
        likeCount: 3
    },
    cardMedia: {
        text: "some test text; badescuga",
        imageUrl: "http://www9.gsp.ro/usr/thumbs/thumb_924_x_600/2016/06/19/738742-rkx1568-lucian-sinmartean.jpg"
    }
};

var card2: CardParams = {
    cardId: "card35335",
    cardType: CardType.Text,
    cardDetails: {
        isLikedByMe: true,
        likeCount: 1
    },
    cardMedia: {
        text: "some test 2 text"
    }
};

var cards = [card1, card2];

ReactDOM.render(
    <div>

        {
            cards.map((item) => {
                return (
                    <Card key={item.cardId} cardId={item.cardId} cardType={item.cardType} cardDetails={item.cardDetails} cardMedia={item.cardMedia}/>
                );
            })
        }
    </div>,
    document.getElementById("mainContainer")
);

无需接触Flux或Redux,而是专注于您的问题。

恕我直言,状态和道具需要分开,其中Card仅获得道具,并且状态是从上方进行管理的。 单击“赞”按钮后, Card组件将获得引发事件处理程序的功能。 您可以在Card组件内执行“喜欢”逻辑,然后仅使用该逻辑的输出引发事件处理程序,例如: this.props.likeClicked(isLikedByMe, updatedLikeCount) 或者,在父组件中执行整个逻辑。 我还将所有卡包装在另一个组件中。

例:

class Card extends React.Component {
  constructor(props: CardParams) {
    super(props);
  }

  render() {
      return (  
        <div>
          <button onClick={this.likeButtonClicked}>
            {this.props.isLikedByMe ? 'Unlike' : 'Like'}
          </button>
          <p>Like count: {this.props.likeCount}</p>
        </div>
      )
   }

    likeButtonClicked = () => {
        console.log('in card => like button clicked!');
        var _isLikedByMe = this.props.isLikedByMe;
        var _likeCount = this.props.likeCount;

        if (_isLikedByMe) {
            _likeCount--;
        } else {
            _likeCount++;
        }

        _isLikedByMe = !_isLikedByMe;

        if (this.props.likeUpdated) {
          this.props.likeUpdated({
            cardId: this.props.cardId,
            isLikedByMe: _isLikedByMe,
            likeCount: _likeCount
          })
        }
    }
}

class CardList extends React.Component {
  constructor(props) {
    super(props) 

    this.state = {
                    // Could use es6 map
                    cards: {123: {isLikedByMe: false, likeCount: 3},
                            124: {isLikedByMe: true, likeCount: 2}}
                  }
  }

  _onLikeUpdated({cardId, isLikedByMe, likeCount}) {    
    const cards = Object.assign({}, this.state.cards)
    cards[cardId] = {isLikedByMe, likeCount}

    this.setState({cards})
  }

  _getCards() {
    return Object.keys(this.state.cards).map(cardId => {
      return <Card key={cardId}
                   cardId={cardId} 
                   likeUpdated={this._onLikeUpdated.bind(this)}   
                   {...this.state.cards[cardId]} />
    })
  }

  render() {
    return <div>
            {this._getCards()}
           </div>
  }
}

小提琴: https : //jsfiddle.net/omerts/do13ez79/

暂无
暂无

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

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