#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 (). Похоже, это пустой массив…
Комментарии:
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:
Эта проблема в основном вызвана неизменяемым объектом. В используемой вами инфраструктуре следует проверить, являются ли состояния неизменяемыми или изменяемыми. Я рекомендую вам просмотреть ссылки, которые я оставил ниже.
Комментарии:
1. Спасибо за ссылки, я посмотрю.