Получение данных вложенного состояния без редуктора с помощью immer

#reactjs

#reactjs

Вопрос:

Я получил data.js который содержит name, listOfReview, которые имеют вложенное состояние (имя, занятие и т. Д.). я использую useReducer, чтобы добавить еще один обзор в listofreview. но проблема в том, что после публикации обзора он создаст новый объект вне listofreview. Вывод

 data.js
export const data = [
    {
        id: 1607089645363,
        name: 'john',
        noOfReview: 1,
        listOfReview: [
            {
                reviewId: 1607089645361,
                name: 'john doe',
                occupation: 'hero',
                rating: 5,
                review: 'lorem ipsum',
            }
        ]
    },
];

index.js
import { data } from '../../src/data';
import { reducer } from './reducer';

const defaultState = {
    review: data
}
const ModalHandler = props => {
    const [rating, setRating] = useState(null);
    const [name, setName] = useState('');
    const [occupation, setOccupation] = useState('');
    const [reviews, setReviews] = useState('');
    const [state, dispatch] = useReducer(reducer, defaultState);

    const handelSubmit = (e) => {
        e.preventDefault();
        if (name amp;amp; occupation amp;amp; reviews) {
            const newReview = { Reviewid: new Date().getTime().toString(), rating, name, occupation, reviews };
            dispatch({ type: 'ADD_REVIEW_ITEM', payload: newReview });
        }
    }
}

reducer.js
    export const reducer = (state, action) => {
    switch (action.type) {
        case "ADD_REVIEW_ITEM":
            return state.map((data) => {
                if (data) {
                    const newReview = [...data.listOfReview, action.payload];
                    return {
                        ...data,
                        listOfReview: newReview
                    };
                }
                return data;
            });
        default:
            return state;
    }
};
 

ВЫВОД
введите описание изображения здесь

Ответ №1:

В соответствии с вашей data структурой, у вас есть array из listOfReview в array из data : — Эти 2 исправления могут вам помочь:-

  1. ИСПРАВЛЕНИЯ 1: вам нужно передать выбранные id из data них, которые вы хотите добавить review в
  2. ИСПРАВЛЕНИЯ 2: вам нужно изменить способ кодирования reducer , чтобы он обновлялся state правильно, а не mutating текущий state

Исправлено 1

  • index.js . Настройте свой handleSubmit для получения arg выбранного id из data тех, которые вы хотите добавить * новый review объект. Таким образом, отправьте как ‘selectedDataId’, так и newReview через dispatch payload
 import { data } from '../../src/data';
import { reducer } from './reducer';

const ModalHandler = props => {
    const [rating, setRating] = useState(null);
    const [name, setName] = useState('');
    const [occupation, setOccupation] = useState('');
    const [reviews, setReviews] = useState('');
    const [state, dispatch] = useReducer(reducer, defaultState);

    const handelSubmit = (e, selectedDataId) => {
        e.preventDefault();
        if (name amp;amp; occupation amp;amp; reviews) {
            const newReview = { Reviewid: new Date().getTime().toString(), rating, name, occupation, reviews };
            dispatch({ 
              type: 'ADD_REVIEW_ITEM', 
              payload: {
                selectedDataId: selectedDataId,
                newReview: newReview
              } 
            });
        }
    }
}
 

Исправлено 2

  • в reducer . Настройте так, чтобы это не mutate было вашим текущим state
 const reducer = (state, action) => {
  switch (action.type) {
    case "ADD_REVIEW_ITEM":
      return {
        ...state,
        review: state.review.map((data) => {
          if (data.id === action.payload.selectedDataId) {
            return {
              ...data,
              listOfReview: [...data.listOfReview, action.payload.newReview]
            };
          }
          return data;
        })
      };
    default:
      return state;
  }
};
 

Это рабочая песочница вашего случая.

Комментарии:

1. я получил ошибку состояния.listOfReview не повторяется

2. Я уже обновил свой ответ выше. Я не видел data , что это array раньше. Итак, выше приведены исправления вашей проблемы

3. Я попытался реализовать исправления, но все же у меня возникли проблемы с состоянием.карта не является функцией — reducer.js

4. Готово, я забыл указать, что у меня есть значение DefaultState

5. я попытался утешить. регистрируйте состояние внутри редуктора, и результат будет таким {обзор: Массив (1)} обзор: Массив (1) 0: {id: 1607089645363, имя: «Андресс Бонифачо», noOfReview: 1, listOfReview: Array(1)} длина: 1 прото : Массив (0) прото : Объект