Мой компонент не рендерится после обновления магазина Redux - PullRequest
3 голосов
/ 15 марта 2019

У меня есть этот компонент меню, где контексты меню изменяются в зависимости от ввода пользователя.

Например, если пользователь нажал кнопку «БРОНИРОВАНИЕ» (рис. 1) в меню, то тело веб-сайта изменится, и менюконтекст изменится для обработки функций резервирования (рис. 2) <--- (желаемое поведение), однако после завершения монтирования компонента перезапуск компонента прекратится. </p>

fig1: |ГЛАВНАЯ |БРОНИРОВАНИЕ |... |etc

fig2: |<|СДЕЛАТЬ БРОНИРОВАНИЕ |... |etc </p>

Что я пробовал:

Похоже, что значения в хранилище меняются и отправляются компоненту тоже.Я пытался использовать componentWillReceiveProps (), но это не сработало.

Вот пример моего компонента меню:

import React, { Component } from 'react';
//redux thingy
import {connect} from 'react-redux';

class DefualtMenu extends Component {


  render() {
    return (
      <div className="Defult-Menu-Main-Div">
        <div className="box1">
          <div className="box11" onClick={() => this.props.HandleMenuClick(this.props.MenuBoxes.box11)}>
            <h3 className="boxh3" onClick={() => this.props.HandleMenuClick(this.props.MenuBoxes.box11)}>
              {this.props.MenuBoxes.box11}
            </h3>
          </div>
        </div>
      </div>
    );
  }
}

const mapDispachToProps = (dispach) => {
  return {
    HandleMenuClick: (buttomName) => {
      switch (buttomName){
        case "RESERVATION":{
          dispach({type: "HANDLE_BODY_CHANGE_RESERVATION"})
          break;
        }
      }
    } 
  }
}

const mapStateToProps = (state) => {
  return {
    MenuBoxes: state.MenuBoxes
  }
}

export default connect(mapStateToProps, mapDispachToProps) (DefualtMenu);

Вот как я выполняю действия:

const reducer = (state = initial_state, action) => {
    const new_state = {...state};

    switch (action.type) {
        }
        case "HANDLE_BODY_CHANGE_RESERVATION": {
            new_state.body = 'reservation';
            if(new_state.userType == 'customer'){
                new_state.MenuBoxes.box11 = '◄'
                new_state.MenuBoxes.box12 = 'DELETE A \n RESERVATION'
                new_state.MenuBoxes.box13 = ''
                new_state.MenuBoxes.box21 = 'MAKE A \n RESERVATION'
                new_state.MenuBoxes.box22 = 'REVIEW \n RESERVATIONS'
                new_state.MenuBoxes.box23 = ''
                new_state.MenuBoxes.box31 = 'UPDATE A \n RESERVATION'
                new_state.MenuBoxes.box32 = ''
                new_state.MenuBoxes.box33 = ''}
            break;
        }
    return new_state;
};

ОБНОВЛЕНИЕ

Я console.log мои состояния: Здесь состояние, когда я вхожу в учетную запись администратора: компонент меню монтируется на этом этапе и всевсе в порядке.

MenuBoxes:
box11: "HOME"
box12: "COUPONS"
box13: ""
box21: "RESERVATION"
box22: "ABOUT US"
box23: ""
box31: "INVENTORY"
box32: "SETTING"
box33: "SIGNOUT"
__proto__: Object
SingInfailureMessege: ""
body: "homepage"
isSignIn: true
showMenu: "default"
userType: "admin"
username: "admin"

Когда я нажимаю на БРОНИРОВАНИЕ -> Компонент меню уже смонтирован здесь, и состояние также изменилось, но компонент не перерисовал и не изменил реквизиты

MenuBoxes:
box11: "◄"
box12: "DELETE A ↵ RESERVATION"
box13: ""
box21: "MAKE A ↵ RESERVATION"
box22: "REVIEW ↵ RESERVATIONS"
box23: ""
box31: "UPDATE A ↵ RESERVATION"
box32: ""
box33: ""
__proto__: Object
SingInfailureMessege: ""
body: "reservation"
isSignIn: true
showMenu: "default"
userType: "admin"
username: "admin"

Ответы [ 3 ]

1 голос
/ 15 марта 2019

Я не согласен, вам не нужно ничего из этого:

componentWillReceiveProps(nextProps) // maybe not this one
componentDidUpdate(prevProps) // probably this one
shouldComponentUpdate(nextProps, nextState) // possibly this one but not likely

Я имею в виду, что это цель реагирования и редукции, изменения состояния -> проверяет, изменен ли реквизит -> если да, то повторная визуализация.Приведенные выше функции полезны для гораздо более сложных случаев, чем этот.

Что неправильно, так это способ написания вашего редуктора.Пожалуйста, попробуйте перейти к чему-то более простому, чтобы проверить.Пожалуйста, попробуйте этот переключатель для начинающих:

  switch (action.type) {
    case "HANDLE_BODY_CHANGE_RESERVATION":
      return { ...state, MenuBoxes: { box11: "test" } };
      break;
    default:
      return state;
      break;
  }

Я уверен, что он будет работать.Тогда начнем с более сложного.

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

const new_state = {...state};

Делая это, вы непосредственно изменяете состояние ниже (мы никогда этого не делаем) .

То, как вы должны это сделать, это создать новый объект, который включает в себя все изменения состояния:

let new_state = {};
...
new_state.body = "reservation";
new_state.MenuBoxes = {};
new_state.MenuBoxes.box12 = "DELETE A \n RESERVATION";

и, в конце, вернуть предыдущее состояние вместе с такими изменениями, как это:

 return { ...state, ...new_state };

Я не эксперт, но я думаю, что сейчас вы изменяете состояние, поэтому новое состояние = старое состояние => повторных визуализаций не требуется

1 голос
/ 15 марта 2019

const new_state = {...state}; хорошо, проблема заключается в мутировании значений MenuBoxes

Вместо этого вам необходимо заменить вложенные объекты и значения из верхней части состояния вниз по пути к конечным значениям, которыенеобходимо изменить.

const reducer = (state = initial_state, action) => {
  switch (action.type) {
    case "HANDLE_BODY_CHANGE_RESERVATION": {
      return { // replace state object with a new object
        ...state, // copy state values to new object as references
        MenuBoxes: { // replace MenuBoxes object with a new object
          ...state.MenuBoxes, // copy Menuboxes values to new object as references
          box11 = '◄',                        // update box values
          box12 = 'DELETE A \n RESERVATION',
          box13 = '',
          box21 = 'MAKE A \n RESERVATION',
          box22 = 'REVIEW \n RESERVATIONS',
          box23 = '',
          box31 = 'UPDATE A \n RESERVATION',
          box32 = '',
          box33 = ''             
        }
      }
    }
};

Во многих случаях, когда требуется глубокое вложение, использование immer является хорошим вариантом.Это сделает автоматически за вас.

import produce from "immer";

const reducer = (state = initial_state, action) => {
  switch (action.type) {
    case "HANDLE_BODY_CHANGE_RESERVATION": {
      return produce(state, draft => {
        draft.MenuBoxes.box11 = '◄'
        draft.MenuBoxes.box12 = 'DELETE A \n RESERVATION'
        draft.MenuBoxes.box13 = ''
        draft.MenuBoxes.box21 = 'MAKE A \n RESERVATION'
        draft.MenuBoxes.box22 = 'REVIEW \n RESERVATIONS'
        draft.MenuBoxes.box23 = ''
        draft.MenuBoxes.box31 = 'UPDATE A \n RESERVATION'
        draft.MenuBoxes.box32 = ''
        draft.MenuBoxes.box33 = ''}
    });
};
0 голосов
/ 15 марта 2019

Вам нужно что-то, что будет проверять наличие изменений в реквизите и обновлять компонент вручную.как

componentWillReceiveProps(nextProps) // maybe not this one
componentDidUpdate(prevProps) // probably this one
shouldComponentUpdate(nextProps, nextState) // possibly this one but not likely

Я сделал пример CodeSandbox, который помог кому-то обновить свой компонент React после изменения Redux.В этом случае я использовал componentDidUpdate ().

https://codesandbox.io/s/88xyxjm30l

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...