反应useReducer异步数据获取

我正在尝试使用新的react useReducer API来获取一些数据,并停留在需要异步获取的阶段。我只是不知道如何:/

如何将数据获取放置在switch语句中,或者这不是应该完成的方式?

import React from 'react'

const ProfileContext = React.createContext()

const initialState = {

data: false

}

let reducer = async (state, action) => {

switch (action.type) {

case 'unload':

return initialState

case 'reload':

return { data: reloadProfile() } //how to do it???

}

}

const reloadProfile = async () => {

try {

let profileData = await fetch('/profile')

profileData = await profileData.json()

return profileData

} catch (error) {

console.log(error)

}

}

function ProfileContextProvider(props) {

let [profile, profileR] = React.useReducer(reducer, initialState)

return (

<ProfileContext.Provider value={{ profile, profileR }}>

{props.children}

</ProfileContext.Provider>

)

}

export { ProfileContext, ProfileContextProvider }

我试图这样做,但它不能与异步一起工作;(

let reducer = async (state, action) => {

switch (action.type) {

case 'unload':

return initialState

case 'reload': {

return await { data: 2 }

}

}

}

回答:

这是一个有趣的案例,useReducer示例没有涉及。我认为减速器不是异步加载的正确位置。来自Redux的心态,您通常会将数据加载到其他位置,例如以thunk,可观察(例如redux-

observable)或仅在生命周期事件中加载componentDidMount。对于新版本,useReducer我们可以使用的componentDidMount方法useEffect。您的效果可能类似于以下内容:

function ProfileContextProvider(props) {

let [profile, profileR] = React.useReducer(reducer, initialState);

useEffect(() => {

reloadProfile().then((profileData) => {

profileR({

type: "profileReady",

payload: profileData

});

});

}, []); // The empty array causes this effect to only run on mount

return (

<ProfileContext.Provider value={{ profile, profileR }}>

{props.children}

</ProfileContext.Provider>

);

}

另外,这里的工作示例:https :

//codesandbox.io/s/r4ml2x864m。

如果您需要将prop或状态传递给reloadProfile函数,可以通过将第二个参数调整为useEffect(示例中的空数组),使其仅在需要时运行。您可能需要检查先前的值或实现某种缓存,以避免在不必要时进行提取。

更新-从孩子重装

如果您希望能够从子组件中重新加载,可以通过以下两种方法进行。第一种选择是将回调传递给子组件,该子组件将触发分派。这可以通过上下文提供程序或组件属性完成。由于您已经在使用上下文提供程序,因此下面是该方法的示例:

function ProfileContextProvider(props) {

let [profile, profileR] = React.useReducer(reducer, initialState);

const onReloadNeeded = useCallback(async () => {

const profileData = await reloadProfile();

profileR({

type: "profileReady",

payload: profileData

});

}, []); // The empty array causes this callback to only be created once per component instance

useEffect(() => {

onReloadNeeded();

}, []); // The empty array causes this effect to only run on mount

return (

<ProfileContext.Provider value={{ onReloadNeeded, profile }}>

{props.children}

</ProfileContext.Provider>

);

}

如果您 确实

想使用分派函数而不是显式回调,则可以通过将分派包装在一个高阶函数中进行处理,该函数处理Redux世界中中间件已经处理过的特殊动作。这是一个例子。请注意profileR,我们传递的自定义变量类似于中间件,而不是直接传递给上下文提供程序,它拦截了reducer无关的特殊操作。

function ProfileContextProvider(props) {

let [profile, profileR] = React.useReducer(reducer, initialState);

const customDispatch= useCallback(async (action) => {

switch (action.type) {

case "reload": {

const profileData = await reloadProfile();

profileR({

type: "profileReady",

payload: profileData

});

break;

}

default:

// Not a special case, dispatch the action

profileR(action);

}

}, []); // The empty array causes this callback to only be created once per component instance

return (

<ProfileContext.Provider value={{ profile, profileR: customDispatch }}>

{props.children}

</ProfileContext.Provider>

);

}

以上是 反应useReducer异步数据获取 的全部内容, 来源链接: utcz.com/qa/431997.html

回到顶部