Ответы пользователя по тегу Redux
  • Правильно ли я понимаю причину ререндеров в react+redux?

    @i1yas
    Предположу что вы делаете так:
    const MyForm = () => {
        const name = useSelector((state) => state.user.form.name);
        const surname = useSelector((state) => state.user.form.surname);
        const email = useSelector((state) => state.user.form.email);
        const agree = useSelector((state) => state.user.form.agree);
    
        ...
    }

    В этом случае даже один селектор тригернет ререндер компонента MyForm

    Нужно переработать форму так, чтобы компонент каждого поля внутри себя использовал useSelector:
    const Field = ({ name, ... }) => {
        const value = useSelector(...);
        ...
    }
    const MyForm = () => {
        return (
           <FormContainer ...>
              <Field name="name"/>
              <Field name="surname"/>
              <Field name="email"/>
              ...
           </Form>
        )
    }


    Собственно, это не специфика редакса, это то как хуки и рендеринг в реакте работают. Если ты подписался на значение, то все компненты ниже по дереву будут ререндериться на каждом апдейте. Общее правило - делать подписку на значение как можно ближе к месту использования этого значения.
    Ответ написан
    3 комментария
  • Почему reducer не видит изменения массива?

    @i1yas
    Документация по редьюсерам https://redux.js.org/basics/reducers
    В частности:
    It's very important that the reducer stays pure. Things you should never do inside a reducer:
    Mutate its arguments;
    Perform side effects like API calls and routing transitions;
    Call non-pure functions, e.g. Date.now() or Math.random().


    Вы мутируете приходящий state

    Чинить надо как-то так:
    export function commentsReducer(state = {data: [], marker: false}, action) {
        switch (action.type) {
            case Comments.ADD_COMMENT: {
                let newData = state.data.slice(); // копируем массив
                newData.push({
                    postId: action.payload.postId,
                    body: action.payload.body,
                    name: action.payload.name,
                    id: state.data[state.data.length - 1].id + 1
                });
                
                // никакого state = ...
                return {...state, is_fetching: false, data: newData};
            }
        }
        return state;
    }
    Ответ написан
    1 комментарий
  • Как обновить один элемент в массиве в Redux?

    @i1yas
    case UPDATE_MESSAGE:
      let foundIndex = state.messages.findIndex(message => message ._id == payload._id);
      state.messages[foundIndex] = payload;
    
        return {
        ...state,
        messages: [...state.messages]
      };

    Redux ругается потому что вы мутируете исходный state. А затем зачем-то создаете новый массив.
    Правильно так:
    case UPDATE_MESSAGE:
      let foundIndex = state.messages.findIndex(message => message ._id == payload._id);
      const messages = state.messages[foundIndex].slice(); // .slice() создаст копию массива
      messages[foundIndex] = payload;
    
        return {
        ...state,
        messages
      };

    Возвращать нужно новый объект (массив), в котором были сделаны изменения.
    Трогать state напрямую нельзя
    Ответ написан
    Комментировать