Получение ошибки типа: state.posts невозможно повторить после того, что, по-видимому, было успешным запросом на публикацию

#javascript #reactjs #redux #react-redux

Вопрос:

Мой текущий проект позволяет пользователю ввести некоторое название и описание и отправляет соответствующее действие. Похоже, он работает нормально, так как отображает CREATE_POST_REQUEST, за которым следует CREATE_POST_SUCCESS с вновь созданным объектом post, возвращенным из вызова API. Однако также прилагается ошибка, в которой говорится: «Ошибка типа: состояние.сообщения не повторяется». У меня есть начальное состояние, которое представляет собой объект, для которого поле posts изначально установлено в пустой массив. Вот несколько фрагментов кода.

postsReducer.js

 import {
    FETCH_POSTS_REQUEST,
    FETCH_POSTS_SUCCESS,
    FETCH_POSTS_FAILURE,
    CREATE_POST_REQUEST,
    CREATE_POST_SUCCESS,
    CREATE_POST_FAILURE
} from "./postsConstants";

const INITIAL_STATE = {
    loading: false,
    posts: [],
    error: '',
};

export const postsReducer = (state = INITIAL_STATE, action) => {
    switch (action.type) {
        case FETCH_POSTS_REQUEST:
            return {
                ...state,
                loading: true,
            }
        case FETCH_POSTS_SUCCESS:
            return {
                ...state,
                loading: false,
                posts: action.payload,
                error: '',
            }
        case FETCH_POSTS_FAILURE:
            return {
                ...state,
                loading: false,
                error: action.payload,
            }
        case CREATE_POST_REQUEST:
            return {
                ...state,
                loading: true,
            }
        case CREATE_POST_SUCCESS:
            return {
                ...state,
                loading: false,
                error: '',
                posts: [...state.posts, action.payload],
            }
        case CREATE_POST_FAILURE:
            return {
                ...state,
                loading: false,
                error: action.payload,
            }
        default: return state;
    }
};
 

postsActions.js

 import {
    FETCH_POSTS_REQUEST,
    FETCH_POSTS_SUCCESS,
    FETCH_POSTS_FAILURE,
    CREATE_POST_REQUEST,
    CREATE_POST_SUCCESS,
    CREATE_POST_FAILURE
} from "./postsConstants";
import * as api from '../../api/posts';

export const fetchPosts = () => {
    return async (dispatch) => {
        try {
            dispatch({
                type: FETCH_POSTS_REQUEST
            });
            const { data } = await api.fetchPosts();
            dispatch({
                type: FETCH_POSTS_SUCCESS,
                payload: data
            });
        } catch (error) {
            dispatch({
                type: FETCH_POSTS_FAILURE,
                payload: error.message
            });
        }
    }
};

export const createPost = (post) => {
    return async (dispatch) => {
        try {
            dispatch({
                type: CREATE_POST_REQUEST
            });
            const { data } = await api.createPost(post);
            dispatch({
                type: CREATE_POST_SUCCESS,
                payload: data
            });
        } catch (error) {
            dispatch({
                type: CREATE_POST_FAILURE,
                payload: error.message
            });
        }
    }
};
 

Compose.js (пользователь вводит название и описание поста)

 import React from 'react';
import { Container, Typography, Button, TextField } from '@material-ui/core';
import { useFormik } from 'formik';
import * as yup from 'yup';
import { useDispatch } from "react-redux";
import { createPost } from "../../redux/index";
import { useHistory } from "react-router-dom";

import useStyles from './styles';

// validation schema
const validationSchema = yup.object({
    title: yup
        .string('Enter a title.')
        .required('A title is required.'),
    description: yup
        .string('Enter a post description.')
        .required('Post description is required.'),
});

function Compose() {;
    const classes = useStyles();
    const dispatch = useDispatch();
    const history = useHistory();

    const formik = useFormik({
        initialValues: {
            title: '',
            description: ''
        },
        validationSchema: validationSchema,
        onSubmit: (values) => {
            dispatch(createPost(values));
        }
    });

    return (
        <Container className={classes.container} maxWidth="lg" >
            <form className={classes.form} autoComplete="off" onSubmit={formik.handleSubmit}>
                <Typography
                    className={classes.header}
                    variant="h3"
                >
                    Compose
                </Typography>
                <Typography
                    className={classes.postLabel}
                    variant="h6"
                >
                    Title
                </Typography>
                <TextField 
                    className={classes.postTitle}
                    name="title"
                    variant="outlined"
                    label="Enter Post Title"
                    fullWidth
                    value={formik.values.title}
                    onChange={formik.handleChange}
                    error={formik.touched.title amp;amp; !!(formik.errors.title)}
                    helperText={formik.touched.title amp;amp; formik.errors.title}
                />
                <Typography
                    variant="h6"
                    className={classes.postLabel}
                >
                    Post
                </Typography>
                <TextField 
                    className={classes.postDescription}
                    name="description"
                    variant="outlined"
                    label="Enter Post Description"
                    fullWidth
                    multiline
                    rows={20}
                    value={formik.values.description}
                    onChange={formik.handleChange}
                    error={formik.touched.description amp;amp; !!(formik.errors.description)}
                    helperText={formik.touched.description amp;amp; formik.errors.description}
                />
                <Button
                    className={classes.buttonSubmit}
                    variant="contained"
                    color="primary"
                    type="submit"
                    size="large"
                    fullWidth                    
                >
                    Publish
                </Button>
            </form>
        </Container>
    )
}

export default Compose;
 

Любая помощь будет признательна, спасибо.

Правка: Забыл добавить некоторые журналы для отображения. журналы при создании новой записи

Правка #2: Добавлена консоль.войдите в журнал, чтобы отобразить свойство state.posts.posts после вызова createPost (). Похоже, это пустой массив…

приставка.регистрируйте результаты после createPost()

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

1. Правильно ли это отображается, когда вы console.log находитесь в своем состоянии?

2. Привет, только что добавил журналы в исходное сообщение, извините за это.

3. Просто добавили консоль. журнал моего состояния.сообщения.сообщения после вызова диспетчера в Compose.js, похоже, что это пустой массив. Добавлено изображение в описание @SamTheFam

4. В своем действии «Сообщения» добавьте журнал консоли data , который вы получили от api.fetchposts() .

5. Инструменты разработки Redux — одни из лучших . Пожалуйста, установите его . Вы можете легко отлаживать свое состояние и действия, отправляемые вместе с информацией о полезной нагрузке.

Ответ №1:

Поскольку ваши данные из api fetch posts возвращают объект с ключевыми сообщениями . Вам нужно изменить отправку, как

 dispatch({
                type: FETCH_POSTS_SUCCESS,
                payload: data.posts
            });
 

Ранее вы получали ошибку, потому что пытались выполнить […состояние.сообщения], где ваши сообщения были объектом, а не массивом .

Ответ №2:

Эта проблема в основном вызвана неизменяемым объектом. В используемой вами инфраструктуре следует проверить, являются ли состояния неизменяемыми или изменяемыми. Я рекомендую вам просмотреть ссылки, которые я оставил ниже.

https://immutable-js.github.io/immutable-js/

https://redux.js.org/faq/immutable-data

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

1. Спасибо за ссылки, я посмотрю.