在React中,我使用context API设置用户数据或API请求返回的错误:

// context
const [currentUser, setCurrentUser] = useState("")
const [error, setError] = useState("")

async function login(credentials) {
    setError("")
    try {
        ...API request
        const data = await response.json()
        if(data.success) {
            setCurrentUser(data)
        } else {
            setError(data.error)
        }
    } catch (error) {
        setError("Something went wrong. Please try again.")
    }
}

<AuthContext.Provider value={login, currentUser, error}>
    {children}
</AuthContext.Provider>

然后在我的组件中:

//component
const { login, currentUser, error } = useContext(AuthContext)

const onSubmit = async (credentials) => {
    setLoading(true)
    await login(credentials)
    resetForm({})
    setLoading(false)
    !error && navigate("/")
}

return (
    ...
)

现在,onSubmit函数允许用户从navigate/,即使context设置了error,这是因为(我认为)在判断error时,error仍然是null,组件没有机会重新加载以获得最新值.

避免这种行为的最佳方法是什么?我应该在组件中本地处理错误,而不是在context中处理错误吗?如果是,在我的场景中,最好的方法是什么?

非常感谢.

推荐答案

Quick solution

当然,还有其他方法可以做到这一点,但不会对您当前的 struct 造成太大改变的方法是更改onSubmit函数,这样您就不会在那里进行重定向:

const onSubmit = async (credentials) => {
    setLoading(true)
    await login(credentials)
    resetForm({})
    setLoading(false)
}

创建一个useEffect来执行重定向,但取决于是否有用户:

useEffect(()=>{
  if(currentUser){
    navigate("/")
  }
},[currentUser])

是的,当您调用!error && navigate("/")时,还没有重新渲染,因此error仍然等于"",这就是重定向立即发生的原因.

Another way

假设登录过程在一个地方处理(大多数情况下都是这样),那么就不需要将login个函数和error个状态作为上下文的一部分.上下文应该只导出setCurrentUsercurrentUser.

<AuthContext.Provider value={currentUser, setCurrentUser}>
    {children}
</AuthContext.Provider>

登录和与登录相关的错误将在登录页面内处理,它将调用setCurrentUser来更新其他组件的上下文:

const {currentUser, setCurrentUser} =  useContext(AuthContext)

当有currentUser时,您将使用与上面相同的useEffect进行重定向.

Javascript相关问答推荐

你怎么看啦啦队的回应?

实现JS代码更改CSS元素

在open shadow—root中匹配时,使用jQuery删除一个封闭的div类

如何使onPaste事件与可拖动的HTML元素一起工作?

我怎么才能得到Kotlin的密文?

如何将多维数组插入到另一个多维数组中?

如何在Press上重新启动EXPO-AV视频?

MongoDB中的嵌套搜索

JAVASCRIPT SWITCH CASE语句:当表达式为';ALL';

P5play SecurityError:无法从';窗口';读取命名属性';Add';:阻止具有源的帧访问跨源帧

更改管线时不渲染组件的react

当达到高度限制时,如何裁剪图像?使用html和css

如何将值从后端传递到前端

如何在不获取其子元素的文本内容的情况下获取元素的文本内容?

在openstreemap/leaflet中,当鼠标在 map 上移动时,如何在小工具提示中实时显示坐标

如何导入我在Web Worker创建的函数?

FiRestore按字段的提取顺序

Chart.js折线图动态更改其y轴

将表单数据转换为多维数组

基于单击按钮更改椭圆的填充/取消填充状态,同时跟踪用户是否 Select 另一种 colored颜色