@Aleksey100

Почему при изменении состояния в redux не рендерится компонент?

Здравствуйте.

У меня такая проблема, при изменении состояния в redux, не происходит рендер компонента который этот state использует.

Компонент Sidebar:
import { getConversations } from '../actions/conversations';

class Sidebar extends Component {
   showChats(thiss){
      return this.props.dialogs.map(function(dialog, key){
         if (!dialog.disable) {
            return (
               <NavLink key={key} to='/dialogs'><SidebarChat dialog={dialog} /></NavLink>
            );
         }
      });
   }
   componentDidMount(){
      this.props.getConversations();
   }
   render() {
      console.log(this.props.dialogs);
      if (this.props.dialogs) {
         return (
            <div className='sidebar'>
               <div className='sidebar__content'>
                  <div className='sidebar__head'></div>
                  <SidebarChatGroup chatName='Общий'>
                     {this.showChats(this)}
                  </SidebarChatGroup>
               </div>
               <div className='sidebar__bg'></div>
            </div>
         );
      }
      else {
         return (
            <div className='sidebar'>
               <div className='sidebar__content'>
                  <div className='sidebar__head'></div>
                  <Preloader />
               </div>
               <div className='sidebar__bg'></div>
            </div>
         )
      }
   }
}

function mapStateToProps(state){
   return {
      dialogs: state.conversations[0]
   };
}

const mapDispatchToProps = (dispatch) => {
    return {
      getConversations: (url) => dispatch(getConversations(url))
    };
};

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


В нем при вызове getConversations(); рендер происходит нормально, но при клике на кнопку (функции openDialog и disableDialog) в компоненте SidebarChat должен изменяться state и соответственно заново рендерится компонент Sidebar
Но этого не происходит. Почему?

Компонент SidebarChat:
import { openConversation, closeConversation } from '../actions/conversations';

class SidebarChat extends Component {
   openDialog(){
      // проверка на открыт ли диалог при клике на диалог в сайдбаре
      // если открыт, то false, если нет, то открываем
      if (this.props.dialog.active) {
         return false;
      } else {
         this.props.openDialog(this.props.dialog.id);
      }
   }
   disableDialog() {
      this.props.closeDialog(this.props.dialog.id);
   };
   render() {
      return (
         <div className={this.props.dialog.active ? "sidebar-chat sidebar-chat__active" : "sidebar-chat" }>
            <div className='sidebar-chat__info' onClick={this.openDialog.bind(this)}>
               <div className='sidebar-chat__name'>{this.props.dialog.visitor.name ? this.props.dialog.visitor.name : this.props.dialog.visitor.uuid.substr(-10)}</div>
               <div className='sidebar-chat__manager'>{this.props.dialog.users.length ? this.props.dialog.users[0].name : 'Нет менеджера'}</div>
               <div className='sidebar-chat__border'></div>
            </div>
            <div className='sidebar-chat__close' onClick={this.disableDialog.bind(this)}></div>
         </div>
      )
   }
}

function mapStateToProps(state){
   return {
      dialogs: state.dialogs
   };
}

const mapDispatchToProps = (dispatch) => {
    return {
      openDialog: (id) => dispatch(openConversation(id)),
      closeDialog: (id) => dispatch(closeConversation(id))
    };
};

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


Action:
export function closeConversation(id) {
    return {
        type: 'CLOSE_CONVERSATION',
        id: id
    };
}

export function openConversation(id) {
    return {
        type: 'OPEN_CONVERSATION',
        id: id
    };
}

export function conversationSuccess(chats) {
    return {
        type: 'CONVERSATIONS_FETCH_DATA_SUCCESS',
        chats: chats
    };
}

export function getConversations() {
    return (dispatch) => {
      setTimeout(function() {
         hubConnection.invoke('GetActiveConversations', null, null, null);
      }, 1500);

      hubConnection.on('ApplyActiveConversations', function (conversations) {
         // добавляем каждому чату свойства (Активный и открытый\закрытый)
         conversations[0].forEach(function(conversation, i){
            conversation.active = false;
            conversation.disable = false;
         });

         dispatch(conversationSuccess(conversations));
      });
    };
}


Reducer:
export function conversations(state = [], action) {
   if (action.type == 'CONVERSATIONS_FETCH_DATA_SUCCESS') {
      return action.chats;
   }
   else if (action.type == 'OPEN_CONVERSATION') {
      let newState = [...state];
      newState[0].forEach(function(dialog, i){
         if (dialog.id == action.id) {
            dialog.active = true;
         }
      });
      return newState;
   }
   else if (action.type == 'CLOSE_CONVERSATION') {
      let newState = [...state];
      newState[0].forEach(function(dialog, i){
         if (dialog.id == action.id) {
            dialog.active = false;
         }
      });
      console.log(newState);
      return newState;
   }
   else {
      return state;
   }
}


Хотя в reducer console.log(newState) выводит измененный, правильный стэйт.
  • Вопрос задан
  • 969 просмотров
Решения вопроса 1
maxfarseer
@maxfarseer
https://maxpfrontend.ru, обучаю реакту и компании
Чего-то здесь не хватает... логика поиска проблемы правильная. Если в вашем редьюсере в консоль падает то, что нужно, значит следуйте дальше: в компонент, где этот редьюсер подключен и смотрите внутри mapStateToProps так же с помощью консоли, изменились данные или нет. Правильно ли вы их подключили и т.д. (получается вам надо проверить и SideBar и SideBarChat)
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы