A
A
Alexey1002018-03-07 11:02:41
JavaScript
Alexey100, 2018-03-07 11:02:41

Why doesn't the component render on state change in redux?

Hello.
I have such a problem, when changing the state in redux, the component that this state uses is not rendered.
Sidebar component:

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);

In it, when calling getConversations(); the rendering happens normally, but when the button is clicked (functions openDialog and disableDialog ) in the SidebarChat component, the state should change and the Sidebar
component is re-rendered accordingly . But this does not happen. Why? SidebarChat
component :
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;
   }
}

Although in the reducer console.log(newState) displays the changed, correct state.

Answer the question

In order to leave comments, you need to log in

1 answer(s)
M
Maxim, 2018-03-07
@Aleksey100

Something is missing here... the problem finding logic is correct. If what you need falls into the console in your reducer, then go further: into the component where this reducer is connected and look inside mapStateToProps also using the console, whether the data has changed or not. Have you connected them correctly, etc. (it turns out you need to check both SideBar and SideBarChat)

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question