我正在尝试从反应减少器内的 api 初始化我的应用程序数据。在化简器上调用 api 和调度,但当函数组件重新呈现时,它仍在使用初始状态。
以下是相关代码:
呃.js
import { useReducer } from 'react';
import api from './api';
const reducer = (state: Object, action: {type: string, data: Object}) => {
switch (action.type) {
case 'init':
return action.data;
}
};
class Ui {
constructor(schematicId) {
const initialState = {loadingStatus: 'Loading...'};
[this.state, this.dispatch] = useReducer(reducer, initialState);
this.schematicId = schematicId;
api.init(schematicId).then(data => {
this.dispatch({type: 'init', data: data});
});
}
}
export default Ui;
索引.js
let alertStore;
let ui;
const App = props => {
alertStore = alertStore || new AlertStore();
ui = ui || new Ui(props.schematicId);
return (
<div className="container-fluid">
{alertStore.alerts.map((a, index) => (
<Alert dismissible key={index}
onClose={() => alerts.remove(index)}
variant={a.variant}>{a.msg}</Alert>
))}
<LoadingBoundary status={ui.state.loadingStatus}>
...
</LoadingBoundary>
</div>
);
};
我原本只是有
alertStore = new AlertStore();
ui = new Ui(schematicId);
但它导致网页冻结。我认为 Ui.js 文件中的某些内容在将其更改为
alertStore = alertStore || new AlertStore();
ui = ui || new Ui(props.schematicId);
因为我以前使用过alertStore = new AlertStore();
,在不同的应用程序中没有问题。
我已经将断点放在 index.js 和 Ui.js. index.js 在 Ui.js 中的 switch 语句之后重新呈现,但状态仍然是 {loadStatus: '正在加载...'} 而不是从 API 返回的状态。
在功能组件中进行 api 调用的正确方法是在 useImpact 中。useEffect文档说,
突变、订阅、计时器、日志记录和其他副作用是 不允许在函数组件的主体内(称为 作为 React 的渲染阶段)。这样做会导致令人困惑的错误和 UI 中的不一致。
相反,请使用 useEffect。传递给 useEffect 的函数将运行 将渲染提交到屏幕后。将效果视为 从 React 的纯功能世界逃生舱口进入命令式 世界。
默认情况下,效果会在每次完成渲染后运行,但您可以 选择仅在某些值发生更改时触发它。[着重号后加]
我将 alertStore 和 ui 声明更改回了原来的样子。
const alertStore = new AlertStore();
const ui = new Ui(props.schematicId);
这意味着每次渲染都会调用new AlertStore
和new Ui
。这没关系,因为 useEffect 可用于确保代码只运行一次,如粗体文档所示。
这是我使用 useEffect 更新的 Ui 类
class Ui {
constructor(schematicId) {
const initialState = {loadingStatus: 'Loading...'};
[this.state, this.dispatch] = useReducer(reducer, initialState);
useEffect(() => {
api.init(schematicId).then(data => {
this.dispatch({type: 'init', data: data});
});
}, [])
this.schematicId = schematicId;
}
}
useEffect 调用的第二个参数[]
告诉 React 这个函数不依赖于组件的任何 props,所以它应该只调用一次。