Reactjs 乐观渲染&;使用效果
TL'DR:在对API调用使用useEffect时,有没有一种方法可以悲观地操作状态更改 假设您编写了一个显示分页/排序数据网格的组件,并为该组件编写了一个类似于此假示例的useEffect:Reactjs 乐观渲染&;使用效果,reactjs,react-hooks,use-effect,Reactjs,React Hooks,Use Effect,TL'DR:在对API调用使用useEffect时,有没有一种方法可以悲观地操作状态更改 假设您编写了一个显示分页/排序数据网格的组件,并为该组件编写了一个类似于此假示例的useEffect: useffect(()=>{ 取回(`https://some-random-api.com/data/page/{paging}/sort/{sorting}`) .then(response=>response.json()) .然后(数据=>setState({ 数据 })); },[分页、排序]
useffect(()=>{
取回(`https://some-random-api.com/data/page/{paging}/sort/{sorting}`)
.then(response=>response.json())
.然后(数据=>setState({
数据
}));
},[分页、排序]代码>按照您描述它的方式,听起来您的组件的其余部分的结构如下
[state, setState] => useState(initialState)
[paging, setPaging] => useState(initialPaging)
[sorting, setSorting] => useState(initialSort)
useEffect(() => {
fetch(`https://some-random-api.com/data/page/{paging}/sort/{sorting}`)
.then(response => response.json())
.then(data => setState({
data
}));
}, [paging, sorting]);
return <div>
<span>Current page is {paging}</span>
<Button onClick={() => setPaging(page => page + 1)}>Nav Next</Button>
<Button onClick={() => setPaging(page => page - 1)}>Nav Prev</Button>
// ... and so on and so forth
</div>
在实践中:
// Make factory instance
const factory = new pessimistFactory();
// Register state and effects
factory.registerState('paging', initialPaging)
factory.registerState('sorting', initialSorting)
factory.registerEffect('fetchData', () => fetch(`https://some-random-api.com/data/page/{paging}/sort/{sorting}`))
// Make the hooks
const {theState, hopefulState, effects} = factory.makeHooks();
// Implement hooks in component
const SomeComponent = () => {
const [state, setState] = theState();
const [pendingState, setPendingState] = hopefulState();
effects.forEach(useEffect => useEffect());
return <div>displayed stuff</div>
}
//生成工厂实例
常量工厂=新工厂();
//登记国和效力
factory.registerState('paging',initialPaging)
factory.registerState('sorting',initialSorting)
registerEffect('fetchData',()=>fetch(`https://some-random-api.com/data/page/{paging}/sort/{sorting}`)
//做钩子
const{theState,hoppentate,effects}=factory.makeHooks();
//在组件中实现钩子
常量SomeComponent=()=>{
const[state,setState]=状态();
常量[pendingState,setPendingState]=希望状态();
effects.forEach(useffect=>useffect());
返回显示的内容
}
最棘手的部分是设置make悲观效果
效果,以读取和处理由生成的setState
s创建的值和回调,我意识到如果在编写时完全破坏了这些值和回调
我现在没有时间真正弄清楚细节,但我认为这必须是可能的,因为有了新的挂钩,比如
不过,我确实喜欢这个想法,所以等我有时间的时候我会想办法解决这个问题。如果您在此之前创建了一个工作工厂类,或者如果有人有一个完全不同的更好的解决方案,我将非常有兴趣看到它。聪明!我可能会这样做,然后将状态放在一个useState中,并使用回调setState API进行更新。或用户教育者。唯一的问题是,我不想重复这种复杂性(对于同一个应用程序中的其他API调用),也不想在依赖项列表增长的情况下维护这种复杂性。我确实想知道是否有办法提取/抽象/封装可重用的钩子。一个UsePessimiceffect钩子,如果你愿意。。。也许有办法。我需要和它玩一会儿。谢谢我同意你关于复杂性和封装性的反馈,我更新了我的答案作为回应。
class pessimistFactory {
constructor(){
this.state = {};
this.effects = [];
}
// util from https://dzone.com/articles/how-to-capitalize-the-first-letter-of-a-string-in
ucfirst = (string) => string.charAt(0).toUpperCase() + string.slice(1);
registerState(param, initialVal){
this.state[param] = initialVal;
}
makePessimisticEffect = (callback, dependencies) => useEffect(() => {
async function handlePessimistically(){
try {
const result = await callback(...dependencies);
// update theState with result
setState({...hopefulState, result})
}catch(err){
// reset hopefulState and handle error
setHopefulState({...theState})
}
}
// Do something if some action pending
if(/* pending and current state not the same */) handlePessimistically();
}, [callback, dependencies]);
registerEffect(callback, dependencies = []){
this.effects.push(
this.makePessimisticEffect(callback, dependencies)
);
}
makeHooks = () => {
const initialState = useState(this.state);
return {
theState: initialState,
hopefulState: initialState,
effects: this.effects
}
}
}
// Make factory instance
const factory = new pessimistFactory();
// Register state and effects
factory.registerState('paging', initialPaging)
factory.registerState('sorting', initialSorting)
factory.registerEffect('fetchData', () => fetch(`https://some-random-api.com/data/page/{paging}/sort/{sorting}`))
// Make the hooks
const {theState, hopefulState, effects} = factory.makeHooks();
// Implement hooks in component
const SomeComponent = () => {
const [state, setState] = theState();
const [pendingState, setPendingState] = hopefulState();
effects.forEach(useEffect => useEffect());
return <div>displayed stuff</div>
}