我正在尝试使用新的reactuseReucker 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 }
}
}
}
我写了一篇非常详细的问题解释和可能的解决方案。丹·阿布拉莫夫提出了解决方案3。
注意:gist中的示例提供了文件操作的示例,但对于数据获取也可以采用相同的方法。
https://gist.github.com/astoilkov/013c513e33fe95fa8846348038d8fe42
保持减速器的纯净是一种很好的做法。它将使useReducer
更具可预测性并简化可测试性。后续方法都将异步操作与纯减速器相结合:
用asyncDispatch(异步调度)包装原始调度,并让上下文传递此函数:
const AppContextProvider = ({ children }) => {
const [state, dispatch] = useReducer(reducer, initState);
const asyncDispatch = () => { // adjust args to your needs
dispatch({ type: "loading" });
fetchData().then(data => {
dispatch({ type: "finished", payload: data });
});
};
return (
<AppContext.Provider value={{ state, dispatch: asyncDispatch }}>
{children}
</AppContext.Provider>
);
// Note: memoize the context value, if Provider gets re-rendered more often
};
const reducer = (state, { type, payload }) => {
if (type === "loading") return { status: "loading" };
if (type === "finished") return { status: "finished", data: payload };
return state;
};
const initState = {
status: "idle"
};
const AppContext = React.createContext();
const AppContextProvider = ({ children }) => {
const [state, dispatch] = React.useReducer(reducer, initState);
const asyncDispatch = () => { // adjust args to your needs
dispatch({ type: "loading" });
fetchData().then(data => {
dispatch({ type: "finished", payload: data });
});
};
return (
<AppContext.Provider value={{ state, dispatch: asyncDispatch }}>
{children}
</AppContext.Provider>
);
};
function App() {
return (
<AppContextProvider>
<Child />
</AppContextProvider>
);
}
const Child = () => {
const val = React.useContext(AppContext);
const {
state: { status, data },
dispatch
} = val;
return (
<div>
<p>Status: {status}</p>
<p>Data: {data || "-"}</p>
<button onClick={dispatch}>Fetch data</button>
</div>
);
};
function fetchData() {
return new Promise(resolve => {
setTimeout(() => {
resolve(42);
}, 2000);
});
}
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.0/umd/react.production.min.js" integrity="sha256-32Gmw5rBDXyMjg/73FgpukoTZdMrxuYW7tj8adbN8z4=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.0/umd/react-dom.production.min.js" integrity="sha256-bjQ42ac3EN0GqK40pC9gGi/YixvKyZ24qMP/9HiGW7w=" crossorigin="anonymous"></script>
<div id="root"></div>
这是一个有趣的案例,useReducer
示例没有涉及到。我认为减速器不是异步加载的合适位置。从Redux的思维模式来看,您通常会在其他地方加载数据,要么在thunk中,要么在可观察的(例如。redux-可观察的)中,要么只是在生命周期事件中,例如组件ddMount
。使用新的useReduer
,我们可以使用use效果
使用组件ddMount
方法。您的效果可以如下所示:
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.
如果需要将道具或状态传递给函数reloadProfile,可以将第二个参数调整为useffect(示例中的空数组),使其仅在需要时运行。您需要对照前面的值进行检查,或者实现某种缓存,以避免在不必要时进行提取。
如果希望能够从子组件重新加载,有几种方法可以做到这一点。第一个选项是将回调传递给将触发调度的子组件。这可以通过上下文提供程序或组件属性完成。由于您已经在使用上下文提供程序,下面是该方法的一个示例:
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世界中中间件处理的特殊操作。这是一个例子。请注意,我们不是将filileR
直接传递给上下文提供程序,而是传递充当中间件的自定义提供程序,拦截还原器不关心的特殊操作。
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>
);
}
问题内容: 我正在尝试使用新的react useReducer API来获取一些数据,并停留在需要异步获取的阶段。我只是不知道如何:/ 如何将数据获取放置在switch语句中,或者这不是应该完成的方式? 我试图这样做,但它不能与异步一起工作;( 问题答案: 这是一个有趣的案例,示例没有涉及。我认为减速器不是异步加载的正确位置。来自Redux的心态,您通常会将数据加载到其他位置,例如以thunk,可
Nuxt.js 扩展了 Vue.js,增加了一个叫 asyncData 的方法,使得我们可以在设置组件的数据之前能异步获取或处理数据。 使用Nuxt.js的异步数据 了解如何使用Nuxt.js管理异步数据。 由VueSchool制作视频课程,用于支持Nuxt.js开发。 asyncData 方法 asyncData方法会在组件(限于页面组件)每次加载之前被调用。它可以在服务端或路由更新之前被调用。
默认情况下,createStore() 所创建的 Redux store 没有使用 middleware,所以只支持 同步数据流。 你可以使用 applyMiddleware() 来增强 createStore()。虽然这不是必须的,但是它可以帮助你用简便的方式来描述异步的 action。 像 redux-thunk 或 redux-promise 这样支持异步的 middleware 都包装了
Nuxt.js 扩展了 Vue.js,增加了一个叫asyncData的方法,使得我们可以在设置组件的数据之前能异步获取或处理数据。 asyncData 方法 asyncData方法会在组件(限于页面组件)每次加载之前被调用。它可以在服务端或路由更新之前被调用。 在这个方法被调用的时候,第一个参数被设定为当前页面的上下文对象,你可以利用asyncData方法来获取数据,Nuxt.js 会将async
本文向大家介绍jQuery异步获取json数据方法汇总,包括了jQuery异步获取json数据方法汇总的使用技巧和注意事项,需要的朋友参考一下 jQuery异步获取json数据有2种方式,一个是$.getJSON方法,一个是$.ajax方法。本篇体验使用这2种方式异步获取json数据,然后追加到页面。 在根目录下创建data.json文件: ■ 通过$.getJSON方法获取json数据 ■
参数: url - 返回JSON格式数据,数据格式与添加(更新)数据定义的data相同 asyncLoadCallback - 当加载完成时执行的回调函数 从一个数据源异步加载数据。用法: var url = "sampleData.json"; // 使用addDataAsync() API异步加载URL中的数据。 // 回调将在完成数据加载后执行。 controller.addDataAsyn