我有一个简单的组件,可以提取数据,然后才显示它:
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
loaded: false
stuff: null
};
}
componentDidMount() {
// load stuff
fetch( { path: '/load/stuff' } ).then( stuff => {
this.setState({
loaded: true,
stuff: stuff
});
} );
}
render() {
if ( !this.state.loaded ) {
// not loaded yet
return false;
}
// display component based on loaded stuff
return (
<SomeControl>
{ this.state.stuff.map( ( item, index ) =>
<h1>items with stuff</h1>
) }
</SomeControl>
);
}
}
MyComponent
的每个实例都从相同的URL加载相同的数据,我需要以某种方式存储它,以避免对服务器的重复请求。
例如,如果我的页面上有10个MyComponent
-应该只有一个请求(提取1个)。
我的问题是存储此类数据的正确方法是什么?我应该使用静态变量吗?还是我需要使用两个不同的组件?
感谢您的咨询!
答案 0 :(得分:2)
您应该考虑使用状态管理库(例如redux),在那里您可以存储所有应用程序状态以及需要数据的组件可以预订。您可以仅在应用程序的根组件中调用一次获取,并且组件的所有10个实例都可以订阅状态。
答案 1 :(得分:1)
如果要仅使用react模拟单个提取调用。然后,您可以从react context API中使用提供方使用者API。在那里,您只能在provider中进行一次api调用,并且可以使用组件中的数据。
const YourContext = React.createContext({});//instead of blacnk object you can have array also depending on your data type of response
const { Provider, Consumer } = YourContext
class ProviderComponent extends React.Component {
componentDidMount() {
//make your api call here and and set the value in state
fetch("your/url").then((res) => {
this.setState({
value: res,
})
})
}
render() {
<Provider value={this.state.value}>
{this.props.children}
</Provider>
}
}
export {
Provider,
Consumer,
}
At some top level you can wrap your Page component inside Provider. Like this
<Provider>
<YourParentComponent />
</Provider>
In your components where you want to use your data. You can something like this kind of setup
import { Consumer } from "path to the file having definition of provider and consumer"
<Consumer>
{stuff => <SomeControl>
{ stuff.map( ( item, index ) =>
<h1>items with stuff</h1>
) }
</SomeControl>
}
</Consumer>
更方便的方法是使用某种状态管理器,例如redux或mobx。您也可以探索这些选项。您可以在这里阅读有关上下文的信息 link to context react website
注意:这是伪代码。有关确切的实现,请参考链接 上面提到的
答案 2 :(得分:1)
如果您想避免使用redux或某种状态管理库,则可以导入一个文件来为您进行提取。遵循这些原则。本质上,缓存存储在fetcher.js文件中。导入文件时,实际上并不是每次都将其导入为单独的代码,因此缓存变量在两次导入之间是一致的。在第一个请求上,将缓存设置为Promise;在后续请求中,承诺仅会返回。
Flux<T>
答案 3 :(得分:1)
您可以使用类似以下代码的方式将活动请求合并为一个承诺:
const f = (cache) => (o) => {
const cached = cache.get(o.path);
if (cached) {
return cached;
}
const p = fetch(o.path).then((result) => {
cache.delete(o.path);
return result;
});
cache.set(o.path, p);
return p;
};
export default f(new Map());//use Map as caching
答案 4 :(得分:1)
如果您的用例建议您在页面上可能包含10个组件,那么我认为您的第二个选择就是答案-两个组件。一个组件用于获取数据并基于数据呈现子级,第二个组件用于接收数据并呈现数据。
这是“智能”和“哑巴”组件的基础。智能组件知道如何获取数据并使用这些数据执行操作,而哑组件只是简单地渲染提供给它们的数据。在我看来,您上面指定的组件本身就太聪明了。
答案 5 :(得分:0)
适用于试图使用功能组件解决问题的人。
如果您只想获取装载时的数据,则可以将一个空数组作为属性添加到useEffect
应该是:
useEffect( () => { yourFetch and set }, []) //Empty array for deps.