Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/433.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 每个组件仅获取一次数据_Javascript_Reactjs - Fatal编程技术网

Javascript 每个组件仅获取一次数据

Javascript 每个组件仅获取一次数据,javascript,reactjs,Javascript,Reactjs,我有一个简单的组件,它获取数据,然后才显示数据: class MyComponent extends React.Component { constructor(props) { super(props); this.state = { loaded: false stuff: null }; } componentDidMount() { // load

我有一个简单的组件,它获取数据,然后才显示数据:

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扩展了React.Component{ 建造师(道具){ 超级(道具); 此.state={ 加载:false 内容:空 }; } componentDidMount(){ //装东西 获取({path:'/load/stuff'})。然后(stuff=>{ 这是我的国家({ 是的, 东西:东西 }); } ); } render(){ 如果(!this.state.loaded){ //尚未加载 返回false; } //基于加载内容的显示组件 返回( {this.state.stuff.map((项,索引)=> 有东西的东西 ) } ); } }
MyComponent
的每个实例都从相同的URL加载相同的数据,我需要以某种方式存储这些数据,以避免向服务器重复请求

例如,如果我在页面上有10个MyComponent,那么应该只有一个请求(1个获取)

我的问题是,存储这些数据的正确方法是什么?我应该使用静态变量吗?或者我需要使用两个不同的组件


谢谢你的建议

> P>您应该考虑使用像ReDux这样的状态管理库,在那里您可以存储所有的应用程序状态和需要数据的组件可以订阅。您可以只在应用程序的根组件中调用一次fetch,并且组件的所有10个实例都可以订阅state。

如果您想使用react only模拟单个fetch调用。然后,您可以使用react上下文API中的提供者-使用者API。在那里,您只能在提供者中进行一次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>
constYourContext=React.createContext({})//根据响应的数据类型,也可以使用数组代替blacnk对象
const{Provider,Consumer}=YourContext
类ProviderComponent扩展了React.Component{
componentDidMount(){
//在此处进行api调用,并将值设置为state
获取(“您的/url”)。然后((res)=>{
这是我的国家({
价值:res,
})
})
}
render(){
{this.props.children}
}
}
出口{
供应商,
消费者,
}
在某些顶层,您可以将页面组件包装到提供程序中。这样地
在要使用数据的组件中。你可以做类似这样的设置
从“具有提供者和使用者定义的文件路径”导入{Consumer}
{stuff=>
{stuff.map((项,索引)=>
有东西的东西
) }
}
更方便的方法是使用某种状态管理器,如redux或mobx。您也可以探索这些选项。你可以在这里阅读上下文

注意:这是psuedo代码。有关具体实现,请参阅链接 上述


如果要避免使用redux或某种状态管理库,可以导入一个文件,该文件将为您执行抓取操作。沿着这条线的东西。实际上,缓存存储在fetcher.js文件中。导入文件时,实际上并不是每次都将其作为单独的代码导入,因此导入之间的缓存变量是一致的。在第一个请求中,缓存被设置为承诺;在后续请求中,承诺刚刚返回

//fetcher.js
让cache=null;
导出默认函数makeRequest(){
如果(!缓存){
cache=fetch({
路径:'/load/stuff'
});
} 
返回缓存;
}
//index.js
从“./fetcher.js”导入fetcher;
类MyComponent扩展了React.Component{
建造师(道具){
超级(道具);
此.state={
加载:false
内容:空
};
}
componentDidMount(){
//装东西
fetcher().then(stuff=>{
这是我的国家({
是的,
东西:东西
});
} );
}
render(){
如果(!this.state.loaded){
//尚未加载
返回false;
}
//基于加载内容的显示组件
返回(
{this.state.stuff.map((项,索引)=>
有东西的东西
) }
);
}

}
您可以使用以下代码将活动请求加入到一个承诺中:

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

如果您的用例表明页面上可能有10个这样的组件,那么我认为您的第二个选项就是答案——两个组件。一个组件用于获取数据并基于数据呈现子级,第二个组件用于接收数据并呈现数据


这是“智能”和“哑”组件的基础。智能组件知道如何获取数据并对这些数据执行操作,而非智能组件只是简单地呈现给它们的数据。在我看来,您上面指定的组件过于智能,不利于自身

供尝试使用功能组件解决此问题的人员使用

如果您只想获取装载时的数据,那么可以将空数组作为属性添加到
useffect

因此,这将是:

useEffect( () => { yourFetch and set }, []) //Empty array for deps.

您可以将fetch作为组件的依赖项,该组件需要由使用者提供,或者将fetch作为包装器导入,以跟踪活动连接并在一个承诺中加入相同的请求。这不能满足以下要求:“如果我在页面上有10个MyComponent,则应该只有一个请求(1个fetch)”