2016-04-01 4 views
1

У меня есть экосистема из 4 взаимосвязанных компонентов, и было бы очень полезно, если бы я мог управлять состоянием одного компонента из другого.Есть ли способ манипулировать состоянием компонента из другого компонента?

Это мой животик компонент:

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; 

Я хочу функцию OpenCard() в компоненте SessionCard вызвать функцию SetState() из компонент MidSection. Есть ли способ добиться этого? Как я могу ссылаться на компонент MidSection (с его текущим состоянием) из компонента SessionCard?

+1

Лучший способ достичь этого - использовать Flux. Я бы предложил Redux как наилучшую реализацию. – Burimi

+0

Если вы хотите попытаться реализовать Flux, посмотрите также altjs. Очень похоже на Redux, но немного меньше кода шаблона – erichardson30

ответ

3

Вы должны установить только состояние из основного (родительского) компонента. Все компоненты для детей должны быть «немыми» компонентами. Проходят в функции которой вы хотите звонить в подпорке SessionCard как:

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

, а затем в вашем OpenCard вызова() функции:

this.props.setStateFunc(); 

Это будет вызывать функцию в родительском компоненте и позволяет вам манипулировать государством оттуда.

0

Большое спасибо @ erichardson30! Несмотря на то, что вашего решения недостаточно, но он направил меня на правильный путь. Передача функции setState() в качестве опоры только передала функцию без контекста (читайте: компонент, на который он должен быть вызван). Итак, я передал ссылку на компонент MidSection сам по себе в качестве опоры, а затем в функцию openCard() я вызвал функцию setState() компонента в своих реквизитах.

В моем животике компоненте:

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

И в моей функции OpenCard():

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

Это точно работает так, как я хотел. Еще раз спасибо! :)

Смежные вопросы