反应useState不更新异步函数中的值

时间:2020-01-12 16:55:46

标签: javascript reactjs asynchronous

const Login = () => {
  const [data, setData] = useState({
    name: "",
    email: "",
    password: ""
  });
  const [isLoading, setIsLoading] = useState(false);
  const [error, setError] = useState(""); // set empty error state

  const handleChange = event =>
    setData({ ...data, [event.target.name]: event.target.value });

  const handleSubmit = async event => { // async function to handle submit
    event.preventDefault();

    try {
      setIsLoading(true);

      const response = await axios.post( // response from server
        "http://localhost:5000/api/users/signup",
        JSON.stringify(data),
        {
          headers: {
            "Content-Type": "application/json"
          }
        }
      );
      console.log(response.data); // data comes back fine
      setIsLoading(false);
    } catch (err) {
      const message = err.response.data.message;
      setError(message); // set error message if there is an error
      setIsLoading(false); // always successfully setLoading to false
      console.log(isLoading); // result is false
      console.log(message); // result message
      console.log(error); // result is still empty string. state never updated with message
    }
  };

我似乎无法弄清楚为什么catch块中的错误状态没有更新。我一直收到一条消息,可以记录该消息,但是状态永远不会更新为该消息。我注意到,如果我在第二次提交时多次提交表单,状态将会更新。

感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

对于任何副作用,例如网络通话,本质上都是异步的数据更新。您必须使用useEffect。这样可以解决问题。要重用逻辑,可以创建自定义钩子。请参见示例:Custom-Hooks

使用效果:

useEffect(
  () => {
    const subscription = props.source.subscribe();
    return () => {
      subscription.unsubscribe();
    };
  },
  [props.source],
);

自定义挂钩:

function FriendStatus(props) {
  const [isOnline, setIsOnline] = useState(null);

  useEffect(() => {
    function handleStatusChange(status) {
      setIsOnline(status.isOnline);
    }

    ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
    return () => {
      ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
    };
  });

  if (isOnline === null) {
    return 'Loading...';
  }
  return isOnline ? 'Online' : 'Offline';
}