使用next-redux-wrapper
时,如何启动长时间的异步任务,使其仅在客户端上运行?我不想在服务器端使用await
,因为它会延迟初始页面加载。我宁愿在任务开始时设置加载标志,并显示加载指示器,直到任务完成。
假设我的异步操作如下:
function async takesLong(store) {
store.dispatch({type: “LOADING”, payload: true});
const result = await longOperation();
store.dispatch({type: “SETDATA”}, payload: data);
return store.dispatch({type: “LOADING”, payload: false});
}
我可以在下一页的getInitialProps
函数中调用此命令,
MyPage.getInitialProps = async ({ store, isServer }) => {
const loader = takesLong(store)
if (isServer) await loader; // <-- will delay client response
return {
someprop: "some value"
};
};
如果页面在客户端上加载,则效果很好。该操作开始,并且在操作完成之前,我的页面可以显示加载程序。但是在服务器端上启动时,该页面完全显示之前有很长时间。我尝试了多种方法,但找不到合适的方法:
await
会呈现页面,而结果不会写入到存储中,因此它仅在存储中将“ loading”设置为true,并且从不获取数据。 / li>
store
中传递props
不起作用-它最终在客户端中成为空对象({ }
)。由于某些原因,试图在组件内部运行它似乎无效:
a)我没有在React组件中访问store
对象(仅在getInitialProps
中无法在客户端上调用)。
b)即使我在组件中使用动作代替store.dispatch
,何时可以安全地调用它?我无法在render
期间执行此操作,因为它将更改Redux状态,并且componentWillReceiveProps
在第一个客户端render
使用Next时,是否存在定义明确的模式将长时间操作推迟到客户端?
答案 0 :(得分:1)
在componentDidMount
上执行长时间异步任务,它将仅在客户端运行。
SSR中的React无法运行componentDidMount
生命周期挂钩。
答案 1 :(得分:1)
在componentDidMount
期间使用绑定动作有效。感谢@eenagy的建议。按此顺序执行操作似乎可以完成所需的操作:
import { bindActionCreators } from "redux";
import { setLoading, setError, setData } from "../actions";
componentDidMount() {
if (!this.props.haveData && !this.props.loading && !this.props.error) {
this.props.setLoading(true);
loadSomeData() // <-- this takes a while to complete
.then( data => {
this.props.setData(data);
this.props.setLoading(false);
})
.catch( err => {
this.props.setError(err);
this.props.setLoading(false);
});
}
}
render() {
if (this.props.loading) return (<Loading/>);
return (/*regular page*/);
}
export const mapDispatchToProps = dispatch => {
return bindActionCreators({ setLoading, setError, setData }, dispatch);
};
export default connect(mapStateToProps, mapDispatchToProps)(Component);
这样,如果尚未加载初始数据(例如由另一页加载),则当 组件安装并异步运行,直到操作完成并 调用redux中的操作导致页面重新呈现。