有没有办法可以从不同的组件操纵组件的状态?

时间:2016-04-01 13:48:20

标签: javascript reactjs

我有一个由4个相互关联的组件构成的生态系统,如果我可以从另一个组件中操纵一个组件的状态,它将非常有用。

这是我的MidSection组件:

import React, {Component} from 'react';
import {render} from 'react-dom';
import $ from 'jquery';
import List from './List';
import OpenSessionCard from './OpenSessionCard';

class MidSection extends Component {  
  constructor() {
    super(...arguments);
    this.state = {
      cardsToBeDisplayed: this.props.sessionCards,
      cardsFilter: 'All',
      cardExpanded: false,
      cardToBeDisplayed: null
    };
  }

  filterCards() {
    let selectedValue = $('#cards-filter').val();
    if (selectedValue === 'All') {
      this.setState({
        cardsToBeDisplayed: this.props.sessionCards,
        cardsFilter: 'All',
        cardExpanded: false,
        cardToBeDisplayed: null
      });
    } else {
      this.setState({
        cardsToBeDisplayed: this.props.sessionCards.filter((sessionCard) => sessionCard.status === selectedValue),
        cardsFilter: selectedValue,
        cardExpanded: false,
        cardToBeDisplayed: null
      });
    }
  }

  render() {
    let cardList, openSessionCard;

    if (!this.state.cardToBeDisplayed) {
      cardList = (
        <List cards={this.state.cardsToBeDisplayed} filter={this.state.cardsFilter}/>
      );
    } else {
      openSessionCard = (
        <OpenSessionCard card={this.state.cardToBeDisplayed}/>
      );
    };

    return (
      <section className="col-md-8 col-sm-12 col-xs-12 middle-section-container">
          <div className="nav-justified pull-left">
              <div className="gray-background-color col-xs-12 form-control-static">
                  <div className="col-xs-6">
                      <label className="control-label green-color" htmlFor="inputError1">MY SESSIONS</label>
                  </div>
                  <div className="col-xs-2 col-xs-offset-4 text-right">
                      <select id="cards-filter" className="form-control" onChange={this.filterCards.bind(this)}>
                        <option>All</option>
                        <option>Open</option>
                        <option>Scheduled</option>
                        <option>Completed</option>
                        <option>Closed</option>
                      </select>
                  </div>
              </div>
              {cardList}
              {openSessionCard}
          </div>
      </section>
    );
  }

  componentDidMount() {
    $('#mid-section').attr('data-rendered', 'true');
  }
}

export default MidSection;

这是我的SessionCard组件:

import React, {Component} from 'react';
import {render} from 'react-dom';
import $ from 'jquery';
import MidSection from './MidSection';

class SessionCard extends Component {
  openCard() {
    /*************
    MidSection.setState({
      cardsToBeDisplayed: null,
      cardsFilter: null,
      cardExpanded: true,
      cardToBeDisplayed: this
    });
    **************/
    $('#cards-filter').attr('disabled', 'disabled');
  }

  render() {
    return (
      <div className="card" onClick={this.openCard.bind(this)}>
        <div className="card__title green-color">{this.props.name}</div>
        <div className="card__details">
          <span>Facilitator: {this.props.facilitator}</span><br/>
          <span>Mode: {this.props.mode}</span><br/>
          <span>Status: {this.props.status}</span><br/>
        </div>
      </div>
    );
  }
}

export default SessionCard;

我希望SessionCard组件中的openCard()函数调用MidSection组件的setState()函数。有什么办法可以实现吗?如何从SessionCard组件中引用MidSection组件(及其当前状态)?

2 个答案:

答案 0 :(得分:3)

您应该只从主(父)组件设置状态。所有儿童成分应该是“愚蠢的”#34;组件。传入你想要调用的功能,如SessionCard的支柱,如:

<OpenSessionCard card={this.state.cardToBeDisplayed} setStateFunc={this.setStateFunc}/>

然后在你的openCard()函数调用中:

this.props.setStateFunc();

这将调用父组件中的函数,并允许您从那里操作状态。

答案 1 :(得分:0)

非常感谢@ erichardson30!尽管你的解决方案并不完全足够,但它引导我走上了正确的轨道。将setState()函数作为prop传递只传递了函数,没有上下文(读取:应该调用它的组件)。所以,我将对MidSection组件本身的引用作为prop传递,然后在openCard()函数中,我在其props中调用了组件的setState()函数。

在我的MidSection组件中:

<OpenSessionCard card={this.state.cardToBeDisplayed} midSectionComponent={this}/>

在我的openCard()函数中:

let midSectionComponent = this.props.midSectionComponent;
midSectionComponent.setState({
  cardsToBeDisplayed: null,
  cardsFilter: null,
  cardExpanded: true,
  cardToBeDisplayed: this
});

它的工作方式与我想要的完全一致。再次感谢! :)