我是React JS的新手,来自iOS,所以尝试实现MVVM。不确定这是不是正确的选择,但这不是我的问题。我想了解react是如何工作的,我做错了什么。下面是我的代码:
const ViewContractViewModel = () => {
console.log('creating view model');
const [value, setValue] = useState<string | null>(null);
const [isLoading, setisLoading] = useState(false);
async function componentDidMount() {
console.log('componentDidMount');
setisLoading(true);
// assume fetchValueFromServer works properly
setValue(await fetchValueFromServer());
console.log('value fetched from server');
setisLoading(false);
}
return { componentDidMount, value, isLoading };
};
export default function ViewContract() {
const { componentDidMount, value, isLoading } = ViewContractViewModel();
useEffect(() => {
componentDidMount();
}, [componentDidMount]);
return (
<div className='App-header'>
{isLoading ? 'Loading' : value ? value : 'View Contract'}
</div>
);
}
所以我知道这里发生了什么:组件已挂载,因此我在视图模型上调用componentDidMount
,这将调用setIsLoading(true)
,从而导致组件的重新呈现,这将导致视图模型重新初始化,然后我们调用componentDidMount
,这是一个循环。
我怎样才能避免这个循环?创建视图模型的正确方法是什么?我怎样才能让代码在组件出现后执行一次?
编辑:为了使我的问题更一般化,我在这里实现MVVM的方式意味着视图模型中useState
的任何声明都将在我们每次调用setXXX
函数时触发一个循环,因为组件将被重新呈现,视图模型将被重新创建,useState将被重新声明。
有没有什么正确的方法?
多谢了!
1条答案
按热度按时间bvn4nwqk1#
React中的一个常见模式是
use{NameOfController}
并使其完全自包含,这样,您就不必手动调用componentDidMount
,而只需在视图中处理常见的UI状态"loading"、"error"和"success"即可。使用上面的例子,你可以编写一个可重用的控制器钩子,如下所示:
然后在视图组件中使用它:
下面是一个演示:
另外,如果你想让你的控制器钩子更动态,并且可以控制初始数据集,那么你可以给它传递props,然后将其添加到
useEffect
依赖项数组中:或者,返回一个可重用的回调函数,该函数允许您在视图组件中重新获取数据: