@Aleksey100

Почему react/redux не рендерит компонент?

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

Не могу разобраться почему redux не инициирует рендер компонента.

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

Sidebar.js
class Sidebar extends Component {
   selectDialog(){
      this.props.selectDialog();
   }
   deleteDialog(){
      this.props.deleteDialog();
   }
   render() {
      console.log('рендер сайдбара');
      return (
         <div className='sidebar'>
            <div className='sidebar__content'>
               <div className='sidebar__head'></div>
               <SidebarChatGroup chatName='Общий'>
                  <button onClick={this.selectDialog.bind(this)}>Выбрать</button>
                  <button onClick={this.deleteDialog.bind(this)}>удалить</button>
               </SidebarChatGroup>
            </div>
            <div className='sidebar__bg'></div>
         </div>
      )
   }
}

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

function mapDispatchToProps(dispatch) {
   return {
      selectDialog: bindActionCreators(actions.selectDialog, dispatch),
      deleteDialog: bindActionCreators(actions.deleteDialog, dispatch)
   }
}

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


Actions
export function selectDialog(dialog) {
   return {
      type: 'DIALOG_SELECTED',
      payload: dialog
   }
}

export function deleteDialog(dialog) {
   return {
      type: 'DIALOG_DELETE',
      payload: dialog
   }
}


Reducer
export default function(state = initialState, action) {
   if (action.type === 'DIALOG_SELECTED') {
      return state;
   }
   if (action.type === 'DIALOG_DELETE') {
      let newState = state;
      newState.shift();
      return newState;
   }
   else {
      return state;
   }
}


Вопрос: Почему так? И как сделать что бы рендер инициировался сам после
newState.shift();
return newState;


И кстати если не просто удалять последний элемент через shift(), а возвращать полностью другой объекта, тогда компонент рендерится автоматически. (под другим объектом я подразумеваю newinitialState, который содержит полностью другие объекты)
  • Вопрос задан
  • 1627 просмотров
Решения вопроса 1
rockon404
@rockon404 Куратор тега React
Frontend Developer
Вы мутируете старое состояние, естетсвенно у вас ничего не работает.
Исправить можно так:
export default function(state = initialState, action) {
   if (action.type === 'DIALOG_SELECTED') {
      return state;
   }
   if (action.type === 'DIALOG_DELETE') {
      const newState = [...state];
      newState.shift();

      return newState;
   }
   else {
      return state;
   }
}


bindActionCreators с connect не используют. Бессмысленно, так как connect сам его вызывает. Так будет лаконичней:
const mapStateToProps = state => ({
  dialogs: state.dialogs,
});

const mapDispatchToProps = {
  selectDialog: actions.selectDialog,
  deleteDialog: actions.deleteDialog, 
};

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


Функции биндить каждый рендер не лучшая идея. Используйте class field function:
class Sidebar extends Component {

   selectDialog = () => {
      this.props.selectDialog();

   };
   deleteDialog = () => {
      this.props.deleteDialog();
   };

   render() {
      console.log('рендер сайдбара');
      return (
         <div className='sidebar'>
            <div className='sidebar__content'>
               <div className='sidebar__head'></div>
               <SidebarChatGroup chatName='Общий'>
                  <button onClick={this.selectDialog}>Выбрать</button>
                  <button onClick={this.deleteDialog}>удалить</button>
               </SidebarChatGroup>
            </div>
            <div className='sidebar__bg'></div>
         </div>
      )
   }
}
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

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

Войти через центр авторизации
Похожие вопросы