Хук состояния не изменяет состояние, React
Есть страница создания новости, при отправке формы, на сервер приходит объект такого типа:
{
title: 'текст примера',
text: 'текст примера'
}
хотя он должен быть таким:
{
title: 'текст примера',
text: 'текст примера',
posted: {
fullDate: "9 сентября 2020 г., 21:56:36",
timestamp: 1599681396,
timeZone: 2,
year: "2020",
month: "9",
day: "9",
hour: "21",
minutes: "56",
seconds: "36"
}
}
Что я делаю не так? Может я не правильно использую хуки состояния?
И ещё по приходу успешного ответа с сервера input[name="title"] почему-то не хочет отчищаться...
Страница создания новости:
import React, { useEffect, useState } from 'react';
import classes from './CreateNews.module.scss';
import classNames from 'classnames';
import { createPostedTime } from '../../functions';
import { createPost } from '../../posts';
import 'react-quill/dist/quill.snow.css';
import UserForm from '../../components/UI/UserForm/UserForm';
import GoBackToAdmin from '../../components/UI/GoBackToAdmin/GoBackToAdmin';
const CreateNews = () => {
const [post, setPost] = useState({
title: '',
text: ''
});
const changeTitleHandler = (e) => {
setPost({
...post,
title: e.target.value
});
}
const changeTextHandler = (e) => {
setPost({
...post,
text: e
});
}
const submitHandler = async (e) => {
e.preventDefault();
setPost({
...post,
posted: createPostedTime()
});
try {
await createPost(post).then((res) => {
setPost({
title: '',
text: ''
});
});
} catch (e) {
console.log(e);
}
}
return (
<div className={classNames('container', classes.CreateNews)}>
<GoBackToAdmin />
<UserForm
title={post.title}
text={post.text}
buttonText="Создать новость"
changeTitle={changeTitleHandler}
changeText={changeTextHandler}
onSubmit={submitHandler}
/>
</div>
)
}
export default CreateNews;
Код компонента UserForm:
import React from 'react';
import classes from './UserForm.module.scss';
import classNames from 'classnames';
import Input from '../Input/Input';
import ReactQuill from 'react-quill';
const modules = {
toolbar: [
['bold', 'italic', 'underline', 'strike'], // toggled buttons
['blockquote', 'code-block'],
[{ 'header': 1 }, { 'header': 2 }], // custom button values
[{ 'list': 'ordered'}, { 'list': 'bullet' }],
[{ 'script': 'sub'}, { 'script': 'super' }], // superscript/subscript
[{ 'indent': '-1'}, { 'indent': '+1' }], // outdent/indent
[{ 'direction': 'rtl' }], // text direction
[{ 'size': ['small', false, 'large', 'huge'] }], // custom dropdown
[{ 'header': [1, 2, 3, 4, 5, 6, false] }],
[{ 'color': [] }, { 'background': [] }], // dropdown with defaults from theme
[{ 'font': [] }],
[{ 'align': [] }],
['image', 'video'],
['clean'] // remove formatting button
]
};
const UserForm = ({title, text, buttonText, changeTitle, changeText, onSubmit}) => {
return (
<form className={classNames(classes.UserForm)}>
<Input
className={classes.UserForm__Title}
title="Название новости"
placeholder="Введите название новости..."
type="text"
name="title"
value={title}
onChange={changeTitle}
/>
<div className={classNames(classes.FormControl)}>
<label htmlFor="text">
Контент новости
</label>
<ReactQuill
id="text"
modules={modules}
theme="snow"
value={text}
onChange={changeText}
/>
</div>
<button
type="submit"
className={classNames('btn', classes.UserForm__SubmitBtn)}
onClick={onSubmit}
>
{buttonText}
</button>
</form>
)
}
export default UserForm;
Функция createPostedTime():
export function createPostedTime() {
const date = new Date();
const timeZone = -date.getTimezoneOffset() / 60;
const fullDate = {
year: 'numeric',
month: 'long',
day: 'numeric',
hour: 'numeric',
minute: 'numeric',
second: 'numeric'
};
const year = {
year: 'numeric',
}
const month = {
month: 'numeric',
}
const day = {
day: 'numeric',
}
const hour = {
hour: 'numeric',
}
const minutes = {
minute: 'numeric',
}
const seconds = {
second: 'numeric'
}
const posted = {};
function timeSave(named, item) {
posted[named] = date.toLocaleString("ru", item);
}
timeSave('fullDate', fullDate);
timeSave('year', year);
timeSave('month', month);
timeSave('day', day);
timeSave('hour', hour);
timeSave('minutes', minutes);
timeSave('seconds', seconds);
posted.timestamp = Math.floor(Date.now() / 1000);
posted.timeZone = timeZone;
return posted;
}
Ответы (1 шт):
Автор решения: Sergei Kirjanov
→ Ссылка
setPost работает асинхронно, и createPost(post) получает старую версию (от последнего рендера).
Можно использовать const postToSend = {...post, .
Или можно делать пост из useEffect, но тут важно не зациклить.
И вообще форма setPost(wasPost=>({...wasPost,title})) безопаснее.