javascript - React Link async/await 不等待代码块

标签 javascript reactjs react-router-dom

嘿,我正在尝试为 React-router 制作小型应用程序,我正在尝试发送 API 请求(我没有后端,这就是我使用 promise 的原因)当我单击“链接”时,它正在重定向,而不是等待我的异步/等待,你能告诉我吗?我做错了什么? 首先想到我可以用 Prop 传递历史,然后

history.push("/someURL");

但我的第二个想法是,如果我可以用

总而言之,我需要等到我的请求( promise )结束后我需要更改网址

import React from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';
import { Link } from 'react-router-dom';
import { toast } from 'react-toastify';

const StyledButton = styled.button`
  width: 100%;
  border-radius: 10px;
  background-color: #24b571;
  color: #ffffff;
  font-weight: bold;
  margin-bottom: 5px;
`;

const SaveButton = ({
  children,
  saveValidation,
  message,
  to,
  setIsLoading,
}) => {
  const promiseFunc = () =>
    new Promise((resolve) => {
      setTimeout(() => {
        resolve(5);
      }, 5000);
    });

  const onClickHandler = async (event) => {
    setIsLoading(true);
    const control = saveValidation(); // returns true or false
    if (!control) {
      toast.error(message);
      event.preventDefault();
    } else {
      try {
        const a = await promiseFunc();
        alert(a);
      } catch {
        alert('error');
      }
      console.log(control);
    }
    setIsLoading(false);
  };

  return (
    <Link to={to}>
      <StyledButton onClick={onClickHandler}>{children}</StyledButton>
    </Link>
  );
};

export default SaveButton;

SaveButton.propTypes = {
  children: PropTypes.node.isRequired,
  saveValidation: PropTypes.func.isRequired,
  to: PropTypes.string.isRequired,
  message: PropTypes.string,
  setIsLoading: PropTypes.func,
};
SaveButton.defaultProps = {
  message: 'Fill all values',
  setIsLoading: () => {},
};

最佳答案

问题

这里的主要问题是您正在渲染用户可以与之交互的两个组件/元素,这通常被认为是 UI/UX 中的反模式。单击按钮并调用其 onClick 处理程序,并且单击事件冒泡,Link 通过导航来处理它。这些事件是彼此分开处理的。您可以在按钮的点击处理程序中停止onClick事件传播,但随后Link将停止工作。

解决方案

我建议单独使用样式按钮,并在异步逻辑问题结束时使用命令式导航,而不是 Link 提供的声明式导航。使用 react-router-dom 中的 useHistory Hook (如果使用 RRDv6,则使用 useNavigate)。

import React from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';
import { useHistory } from 'react-router-dom'; // <-- import hook
import { toast } from 'react-toastify';

const StyledButton = styled.button`
  ...
`;

const SaveButton = ({
  children,
  saveValidation,
  message,
  setIsLoading,
  to,
}) => {
  const history = useHistory(); // <-- use hook

  const promiseFunc = () => new Promise((resolve) => {
    ...
  });

  const onClickHandler = async (event) => {
    setIsLoading(true);
    const control = saveValidation();
    if (!control) {
      toast.error(message);
      event.preventDefault();
    } else {
      try {
        const a = await promiseFunc();
        alert(a);
      } catch {
        alert('error');
      }
      console.log(control);
    }
    setIsLoading(false);
    history.push(to); // <-- imperative navigation
  };

  return (
    <StyledButton onClick={onClickHandler}>{children}</StyledButton>
  );
};

关于javascript - React Link async/await 不等待代码块,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70237476/

相关文章:

javascript - 如何在每个路由中渲染相同的组件

reactjs - 如何使用 React 路由器和 Spring Boot Controller

javascript - 如何在 Home Route 中正确设置 react-router-dom?

javascript - 将更改推送到已部署的 Meteor.js 应用程序

javascript - 创建一个具有随机名称的函数并稍后调用它

javascript - React Native - 使用异步数据填充 ListView

reactjs - 将 props 传递给 hook 组件变得未定义

reactjs - 为什么我的 React 应用程序将外部 URL 附加到 http ://localhost:/<port> and not to ONLY the URL itself?

javascript - 如何从嵌入标签中获取 svg 元素?

javascript - 通过用户名从 Spotify 获取公共(public)播放列表