我有一个组件,可以在页面上多次使用。它的作用是进行外部调用,并将该外部调用中的值保存到键对象中的redux存储中。我只希望组件执行一次此操作,因此我正在使用componentDidMount。现在,如果同一组件再次在页面上使用,我不希望它再次执行外部调用。这在使用类时可以正常使用,但是当我尝试使用函数挂钩时,它将不再起作用。 让我开始向您展示基于类的代码。
class MyComponent extends Component {
componentDidMount() {
setTimeout(() => this.wait(), 0);
}
wait() {
const { key, map } = this.props;
if (map[key] === undefined) {
saveKey(key);
console.log('LOAD EXTERNAL ID ONLY ONCE');
externalAPI(this.externalHandler.bind(this));
}
}
externalHandler(value) {
const { key, setValue } = this.props;
setValue(key, value);
}
render() {
const { key, map children } = this.props;
return (
<>
{children}
</>
);
}
}
mapStateToProps .....
export default connect(mapStateToProps, { saveKey, setValue })(MyComponent);
Reducer.js
export default (state = {}, action = null) => {
switch (action.type) {
case SAVE_KEY: {
return {
...state,
[action.id]: 'default',
};
}
case SET_VALUE: {
const { id, value } = action;
return {
...state,
[id]: value,
};
}
default: return state;
}
};
Page.js 如下调用每个组件。
import React from 'react';
const Page = () => {
return (
<>
<MyComponent key='xxxxx'>First Component</MyComponent>
<MyComponent key='xxxxx'>Second Component</MyComponent>
</>
);
};
export default Page;
以上所有作品。因此,当第一个组件挂载时,我延迟了对redux的调用,不确定为什么会起作用,但确实可以。有人可以告诉我为什么使用setTimeout有效吗???而没有使用setTimeout则不会。通过工作,我的意思是超时,因为map [key] === undefined,第一个组件安装了set key。第二个组件挂载map [key]不再是未定义的。但是没有超时map [key]总是=== undefined吗?
它将通过的密钥prop存储在redux中。第二个组件将挂载并看到存储了相同的密钥,因此它无需再次调用外部API getExternalID。如果第三个组件安装了其他密钥,则应再次运行外部API调用,依此类推。
正如我所说的,以上所有工作均有效,但我不确定为什么需要执行setTimout才能使其正常工作。
第二个问题,将其转换为函数并进行钩子而不是类。由于某些原因,这不起作用。
import React, { useEffect } from 'react';
const MyComponent = ({ children, key, map, saveKey, setValue }) => {
useEffect(() => {
setTimeout(() => delay(), 0);
}, [map[key]]);
const delay = () => {
if (map[key] === undefined) {
saveKey(key);
console.log('LOAD VARIANT ONLY ONCE');
externalAPI(externalHandler);
}
};
const externalHandler = (value) => {
setValue(key, value);
};
return (
<>
{children}
</>
);
};
export default MyComponent;
答案 0 :(得分:0)
第一个问题:
JavaScript使用单个线程工作,因此即使您使用延迟0毫秒,该方法也会在React的render方法退出后被调用。我相信这是一个实验,对此可以进行解释:
function log(msg){
$("#output").append("<br/>"+msg);
}
function render(){
log("In render");
log("Delayed by 0 ms without setTimeout...")
setTimeout(() =>log("Delayed by 0 ms with setTimeout..."), 0);
for(var i = 0;i<10;i++) log("Delay inside render "+i);
log("Render finish");
}
render();
https://jsfiddle.net/hqbj5xdr/
因此,实际上所有组件在开始检查map [key]是否未定义之前都会渲染一次。
第二个问题:
在您的示例中,并不清楚map和saveKey的来源。以及组件之间如何共享地图...
无论如何,天真的解决方案是直接更新地图。并确保所有组件 引用此地图实例(不是副本)。
if (map[key] === undefined) {
map[key]=true;
saveKey(key);
console.log('LOAD VARIANT ONLY ONCE');
externalAPI(externalHandler);
}
但这有点不好(共享参考)。因此,更好的设计可能是使用缓存。不要传递地图,而是传递获取器和传递器。 getKey和saveKey。这些方法的基础可能是使用地图来保留已设置的键。