状态似乎不会立即改变

时间:2020-01-27 20:06:47

标签: reactjs redux react-redux react-hooks

import React, { useState, useEffect } from "react";
import { useSelector, useDispatch } from "react-redux";
import { editZoneMaster } from "../../../redux/actions/GeneralMaster/ZoneMaster";
export default function ModalForm() {
  let dispatch = useDispatch();
  const [formData, setFormData] = useState({});
  const [state, setState] = useState({
    open: false
  });
  const UI = useSelector(state => state.UI);
  const handleOpen = () => {
    setState({
      ...state,
      open: true
    });
  };
  const handleClose = () => {
    setState({
      ...state,
      open: false
    });
  };
  const onChange = e =>
    setFormData({ ...formData, [e.target.name]: e.target.value });

  const handleSubmit = async e => {
    e.preventDefault();
    dispatch(editZoneMaster(formData));
    console.log(UI.errors)
    console.log(Object.keys(UI.errors).length)
    if (Object.keys(UI.errors).length === 0) handleClose();
  };

控制台输出:

Output from my console

我正在尝试验证我的表单,以防止用户在检测到任何错误时关闭模式。在第一个提交时不会记录错误,仅在第二个提交时会记录。状态已正确更改。而且在返回错误时,它运行良好。但不在渲染上。

2 个答案:

答案 0 :(得分:0)

在分派后立即记录状态不会向您显示新状态,因为分派动作是异步的,即,影响状态需要花费时间(通常是很短的时间)。

要跟踪对象中的更改,应使用useEffect钩子,如下所示:

useEffect(() => {
    console.log(UI.errors);
    console.log(Object.keys(UI.errors).length);
}, [ UI.errors ]);

(并从handleSubmit中删除console.log调用)

答案 1 :(得分:0)

这是因为UI仅在下一个渲染中会更改。没有魔术绑定,UI值更改在分派后立即反映出来。如果您想在分派后立即获得经过验证的值,则需要使用useStore钩子(https://react-redux.js.org/next/api/hooks#usestore),如下所示:

import React, { useState, useEffect } from "react";
import { useSelector, useDispatch, useStore } from "react-redux";
import { editZoneMaster } from "../../../redux/actions/GeneralMaster/ZoneMaster";
export default function ModalForm() {
  let dispatch = useDispatch();
  const [formData, setFormData] = useState({});
  const [state, setState] = useState({
    open: false
  });
  const UI = useSelector(state => state.UI);
  const store = useStore();
  const handleOpen = () => {
    setState({
      ...state,
      open: true
    });
  };
  const handleClose = () => {
    setState({
      ...state,
      open: false
    });
  };
  const onChange = e =>
    setFormData({ ...formData, [e.target.name]: e.target.value });

  const handleSubmit = async e => {
    e.preventDefault();
    dispatch(editZoneMaster(formData));
    const updatedUI = store.getState().UI; // this is now updated UI state
    console.log(updatedUI.errors)
    console.log(Object.keys(updatedUI.errors).length)
    if (Object.keys(updatedUI.errors).length === 0) handleClose();
  };

但是说实话,我更喜欢这种方法(我认为更干净):

import React, { useState, useEffect } from "react";
import { useSelector, useDispatch, useStore } from "react-redux";
import { editZoneMaster } from "../../../redux/actions/GeneralMaster/ZoneMaster";
export default function ModalForm() {
  let dispatch = useDispatch();
  const [formData, setFormData] = useState({});
  const [state, setState] = useState({
    open: false
  });
  const UI = useSelector(state => state.UI);

 useEffect(() => {        
    console.log(UI.errors)
    console.log(Object.keys(UI.errors).length)
    if (Object.keys(UI.errors).length === 0) handleClose();}, [setState, UI]);

  const handleOpen = () => {
    setState({
      ...state,
      open: true
    });
  };
  const handleClose = () => {
    setState({
      ...state,
      open: false
    });
  };
  const onChange = e =>
    setFormData({ ...formData, [e.target.name]: e.target.value });

  const handleSubmit = async e => {
    e.preventDefault();
    dispatch(editZoneMaster(formData));
  };

检查验证并在更改后关闭UI的位置。两种解决方案都是有效的。

希望这会有所帮助。