Redux: обновить данные родительского компонента после дочерних операций

У меня есть некоторые данные, загруженные в store после первоначального вызова Axios.

Затем я визуализирую два компонента match (родительский компонент) и player (дочерний компонент).

Это способ показать два компонента связанным образом (это упрощенный пример из моего исходного кода, в этом примере я мог бы решить свою проблему по-другому, но в моем сложном реальном коде важно выполнять операции в сначала дочерний компонент):

match.js

class Match extends Component {

  constructor(props) {
    super(props);
  }
 
  render() {
    return (    
      Object.values(this.props.matchs).map(( match_id ) => {
        let match = this.props.matchs[match_id];
        return (
         <div key={match_id}>
          <p>{match.tournament}</p>          
          <p>{match.color}</p> {/* this color depends of children condition*/ }
          <div className="players">
              {match.array_players.map ( ( player_id ) => {
                let player = this.props.players[player_id];
                  return (
                    <Player key={odd_id} ownPlayer={player} />
                  )
                })
          </div>
         </div> 
       )
      });    
    )  
  }
  
}

const mapStateToProps = state => {  
    return {
      matchs: state.matchs.matchs,
      players: state.players.players      
    };
  }
  
  const mapDispatchToProps = dispatch => {
    return {
      // actions
    };
  }
export default connect(mapStateToProps, mapDispatchToProps)(Matchs);

player.js

class Player extends Component {

  constructor(props) {
    super(props);
  } 

  render() {    
    
    return (

        <div>
          <p>{this.props.ownPlayer.name}</p>
          <p>{this.props.player_color}</p>
        </div>
    );
  }
}

const mapStateToProps = (state, ownProps) => {

  // I need to make some previous operations before render
  let player_color;
  if (ownProps.ownPlayer.name == "paul")
    player_color = 'yellow';
  else
    player_color = 'blue';
    
  // Then I Need to update parent component with children color condition
  // if (player_color == 'yellow')
  //  match_color = 'yellow'
  //    
  // Call some action here to update parent component???
  // things like these do not work: 
  // let id_p = ownProps.player.id_player;
  // state.players.players[id_p].color = 'blue'; This does not work


  return {    
    player_color
  };
};

const mapDispatchToProps = dispatch => {
  return {
    //
    }
  };
}

export default connect(mapStateToProps, mapDispatchToProps)(Player);

Затем мне нужно обновить реквизит в родительском компоненте после некоторых условий в дочернем компоненте.

Я прочитал эту статью:

https://redux.js.org/docs/recipes/ComputingDerivedData.html

Но я не знаю, как отправлять данные для хранения и обновления родительского компонента перед рендерингом.

Я думал о том, чтобы вызвать действие в componentWillMount или componentWillUpdate для отправки данных в хранилище, но я не знаю, правильно ли это.


person kurtko    schedule 26.12.2017    source источник
comment
если ваш дочерний компонент получает два реквизита (которые являются его переменными) непосредственно от своего родителя, то почему вы не можете вычислить значение этого родительского реквизита внутри самого родителя?   -  person Bruno Braga    schedule 26.12.2017
comment
Это упрощенный пример, но в моем реальном коде мне нужно сделать некоторые сложные вычисления в дочерних элементах, а затем, в зависимости от этих вычислений, обновить цвет родительского компонента (сопоставить)   -  person kurtko    schedule 26.12.2017


Ответы (2)


Нет ничего плохого в вызове действия внутри жизненного цикла, не рекомендуется делать это внутри метода рендеринга, потому что это запускает бесконечные действия, но в вашей ситуации, если вам действительно нужно выполнить этот расчет внутри дочернего компонента, я считаю, что вы должны отправить это действие внутри componentWillReceiveProps или ComponentDidMount, в некоторых ситуациях вам действительно нужно сделать это в обоих местах.

Действуй!

person Bruno Braga    schedule 26.12.2017

документы довольно ясны:

Вы можете выполнять однократные операции в constructor / ComponentWillMount / ComponentDidMount или повторяющиеся операции в повторяющихся методах жизненного цикла, таких как ComponentWillReceiveProps.

Если вам нужен способ для дочернего компонента обновить хранилище, вам нужно dispatch выполнить действие, которое будет выполняться, и поместить его в ComponentWillMount или ComponentWillReceiveProps в зависимости от необходимости, иногда вам нужно поместить его в оба.


Но, с другой стороны, как сказал Бруно Брага, это кажется неправильным местом для размещения логики. Я бы предложил поместить эту логику в редуктор, поскольку компонент действительно не должен обрабатывать логику хранения, просто уведомить (dispatch) изменения состояния.

Кроме того, я не думаю, что вам нужно подключать компонент Player к магазину редукса, так как кажется, что у каждого игрока есть свой независимый экземпляр.

Я бы предложил передать компоненту Player функцию из компонента Match, что-то вроде

<Player ... onGoalScored={()=> this.handleGoalScored()} />

и в компоненте Match выполните:

handleGoalScore() { this.props.dispatch(updateGoalsAction()) }

и иметь логику в редукторе, скажем, выяснит, каким должен быть цвет Match, и при следующем обновлении состояния до Match из-за привязки к store.matchs.color будет отображаться как красный

person Daniel Dubovski    schedule 26.12.2017