使用具有redux和redux thunk操作的react路由器V6导航的最佳方式是什么



我正在使用react-v17react-reduxV7和react Router V6制作一个react应用程序(非本地react(,搜索和阅读了许多文章,我找不到一种使用V6钩子在redux操作中以编程方式导航的方法,因为钩子只能在组件内部调用,以下是我的

registerPage.jsx

import React, { Component } from 'react'
import { useParams, useNavigate } from 'react-router-dom'
import { useEffect, useState } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { LockClosedIcon } from '@heroicons/react/solid'
import Loader from 'react-loader-spinner'
import { registerUser } from '../../../state_man/store/register'
const RegisterForm = (props) => {
const [registerFields, setRegisterFields] = useState({})
const [errors, setErrors] = useState({})
const [validInput, setValidInput] = useState({})
const [loading, setLoading] = useState(false)
let navigate = useNavigate()
let params = useParams()
let auth = useSelector((state) => state.auth)
let mainUi = useSelector((state) => state.UI.mainUI)
let registerUi = useSelector((state) => state.UI.registerPage)
const dispatch = useDispatch()
const { isLoggedIn } = auth
const onRegisterUser = (e) => {
e.preventDefault()
const credentials = {
username: registerFields['username'],
['phone']: registerFields['phone'],
email: registerFields['email'],
region: registerFields['region'],
password: registerFields['password'],
address: registerFields['address'],
client_name: registerFields['client_name'],
}
dispatch(registerUser(credentials))
return (
// my form is so long, i made it short just for demonstration purposes! 
<form>
<input type='text' />
<input type='passowrd' />
<button
onClick={(e) => {
// here i call the function that does the registration ,
//that included calling a function that dispatches API action,
onRegisterUser(e)
}}
></button>
</form>
)
}

在我的状态管理模块中,我创建了一个调度API操作的函数

register.js

const url = '/client'
export const registerUser = (credentials) => {
return apiActionCreators.apiCallBegan({
url,
method: 'post',
data: credentials,
onStart: START_LOADING.type,
onEnd: END_LOADING.type,
onSuccessFunc: (data) => (dispatch, store) => {
dispatch(USER_REGISTERED(data))
dispatch(CLEAR_MAIN_ERROR())
// i want to take the user to a specific page using something like navigate("menu")
},
onErrorFunc: (error) => (dispatch, store) => {
dispatch(ADD_MAIN_ERROR(error))
},
})
}

正如我所评论的,我想在";onSuccessFunc";以便将用户带到特定页面,我知道我可以制作一个减速器并将其用于导航,我将带有有效载荷的动作发送到我想要导航的地方,在HOC中,我检查是否有要导航的路径,如果我是真的,我会清除它并导航,诸如此类的事情!

let navigation = useSelector((state) => state.navigation)
useEffect(() => {
if (navigation.path) {
dispatch(
navigationActions.CLEAR_NAVIGATION_PATH()
)
navigate('/navigation.path')
}
}, []) 

这似乎是一个很好的解决方案,我认为可能有很多DRY和缺点,做这件事最好的方法是什么!你看到我的解决方案有什么缺点吗!,请记住,我使用的是react路由器V6!谢谢

您最好直接在回调中进行导航。你可以利用钩子的规则:从自定义钩子调用钩子。

// register.js or useRegister.js
export const useRegisterUser = () => {
const navigate = useNavigate();
const doRegister = (credentials) => {
return apiActionCreators.apiCallBegan({
url,
method: 'post',
data: credentials,
onStart: START_LOADING.type,
onEnd: END_LOADING.type,
onSuccessFunc: (data) => (dispatch, store) => {
dispatch(USER_REGISTERED(data))
dispatch(CLEAR_MAIN_ERROR())
// allowed since it's inside a hook
navigate("menu")
},
onErrorFunc: (error) => (dispatch, store) => {
dispatch(ADD_MAIN_ERROR(error))
},
})
}
return {
doRegister 
}
}
// registerPage.js
import { useRegisterUser } from './register.js'
// other imports 
const RegisterForm = (props) => {
const { doRegister } = useRegisterUser()
// other stuffs
// grab credentials
dispatch(doRegister(credentials))
// other stuffs
return (<></>)
}

对我来说,我正试图等待用createAsyncThunk创建的函数的结果。我知道使用dispatch,但不确定如何在成功或失败时做任何事情。我在这里的redux文档中找到了答案。原来,调度返回的操作可以传递到fulfilledrejected等异步函数的属性中,这些属性是为检查其响应状态而创建的。

相关章节:

const handleUpdateUser = async (userData) => {
const resultAction = await dispatch(updateUser(userData))
if (updateUser.fulfilled.match(resultAction)) {
const user = resultAction.payload
showToast('success', `Updated ${user.name}`)
} else {
if (resultAction.payload) {
// Since we passed in `MyKnownError` to `rejectValue` in `updateUser`, the type information will be available here.
// Note: this would also be a good place to do any handling that relies on the `rejectedWithValue` payload, such as setting field errors
showToast('error', `Update failed: ${resultAction.payload.errorMessage}`)
} else {
showToast('error', `Update failed: ${resultAction.error.message}`)
}
}
}

并且更具体地使用CCD_。

我用这个在登录后做导航。以下是我的登录提交功能。

const handleLoginSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
const formData = new FormData(event.currentTarget);
const email: string = formData.get('email') as string;
const password: string = formData.get('password') as string;
if (!email || !password) {
return;
} else {
const resultAction = await dispatch(loginAsync({ email, password }))
if (loginAsync.fulfilled.match(resultAction)) {
navigate('/dashboard');
} else if (loginAsync.rejected.match(resultAction)) {
console.log('Failed!');
}
}
}

在搜索和阅读一些评论后,我找到了3种可能的解决方案,第一个答案是第一个,但我不太喜欢使用它,因为我不知道钩子的实现细节,我试过了,效果很好,第二个选项是创建您自己的CustomRouter,给它一个您创建的history对象,并按照此处的指定对您创建的历史对象进行更改:https://stackoverflow.com/a/70012117/8690857,感谢德鲁的指出。第三个是使用一个可以从RRDv6导入的对象,称为unstable_HistoryRouter,您也可以在这里找到它https://stackoverflow.com/a/70012117/8690857.

最新更新