React Reuse获取整个组件中的JSON数据

时间:2018-09-26 01:32:44

标签: javascript json reactjs fetch

嗨,我是React的新手,并在我的整个项目中学习了可重用功能。

我想获取我的JSON数据,但不必每次都在组件中调用它。

App.js

import React, { Component } from 'react';
import { Route, NavLink, HashRouter } from "react-router-dom";

import logo from '../assets/logo.png';
import './app.css';

import About from "../about/about";
import Services from "../services/services";
import Testimonials from "../testimonials/testimonials";
import Contact from "../contact/contact";

class App extends Component {
constructor(props) {
    super(props);
    this.state = {
       items : []
    };
}
componentDidMount(){
  this.getItems();
}
getItems(){
  fetch('./data/data_arr.js')
  .then(results => results.json())
  .then(results => this.setState({'items': results}));
}
render() {
 return (
  <HashRouter>
    <div className="container">
      <div className="header">
        <div className="App-logo"><NavLink exact to="/"><img src={logo} alt="logo" /></NavLink></div>
        <nav className="Nav-Desktop">
        {this.state.items.map((item, index) => (
          <div key={index}>
          {
            item.links.map((link, i) => (
            <NavLink key={i} exact to={link.url}>{link.text}</NavLink>
          ))}
          </div>
        ))}
        {
          this.state.items.map((item, index) => {
            return <div key={index}><a href={item.mainContact.phoneHref + item.mainContact.phone}><i className="fa fa-phone"></i><strong> {item.mainContact.phone}</strong></a></div>
          })
        }
        </nav>
      </div>
      <main className="content">
         <Route exact path="/" component={About}/>
         <Route path="/services" component={Services}/>
         <Route path="/testimonials" component={Testimonials}/>
         <Route path="/contact" component={Contact}/>
      </main>
      {this.state.items.map((item, index) => {
        return <footer key={index}>&copy; Copyright {item.title} {(new Date().getFullYear())}</footer>
      })
      }
    </div>
    </HashRouter>
    );
  }
}
export default App;

我已经成功映射了数据并显示了数据,但是我还有其他包含此代码段的文件

constructor(props) {
    super(props);
    this.state = {
       items : []
    };
}
componentDidMount(){
  this.getItems();
}
getItems(){
  fetch('./data/data_arr.js')
  .then(results => results.json())
  .then(results => this.setState({'items': results}));
}

我曾尝试像这样将getItems()导出到helper.js文件中,然后导入文件import { getItems } from '../helpers/helpers';,但是代码无法正常工作并卡在Unhandled Rejection (TypeError): Cannot read property 'setState' of undefined

export function getItems() {
    fetch('./data/data_arr.js')
    .then(results => results.json())
    .then(results => this.setState({'items': results}));
}

如果任何人都可以向我指出错误/正确的解决方法,这将有所帮助。干杯

4 个答案:

答案 0 :(得分:2)

当您要重用数据而不是一次又一次地调用fetch时,需要了解两点

  1. 在最顶层的组件(即父组件)中进行调用,并将数据传递给所有子组件,子组件传递给子组件,但是请记住,这对您来说很忙。当您构建小型应用程序时(例如最多50个组件),这种方法非常有用。但是,当您的应用程序变大时,这不是在组件之间重用数据的推荐方法。

  2. 使用Redux状态管理库来实现跨组件的数据可重用性。这就像您的应用程序的集中存储。这些天主要在每个React应用中使用。使用Redux,您可以在父组件中进行操作调用,该操作实际上将获取数据并将其传递给reducer。因此,现在reducer将在Redux存储中设置数据。现在,通过使用state.get从Redux存储中获取数据,可以在每个组件中访问数据。因此,您可以调用redux操作,例如this.props.getItems();。无论您在哪里需要组件中的数据,组件mapStateToProps都会使这些数据作为道具可供您的组件使用

如何从Redux存储中获取数据?

在component中定义一个函数mapStateToProps,并使用state.get从Redux存储中获取数据,然后将其返回给函数。传递mapStateToProps连接方法。您将把组件连接到名为connect的Redux HOC组件。此connect方法接受操作和Redux状态,并使它们作为道具可用于组件。

关于您的问题

   Unhandled Rejection (TypeError): Cannot read property 'setState' of undefined

出现此问题的原因是,导出的getItems函数中没有此问题。

您需要解决的问题是将其作为参数传递给getItems函数

注意:这是当前上下文

 import { getItems } from '../helpers/helpers';

 componentDidMount(){
     getItems(this);
 }

helpers.js:

 the below function is treated as a normal JavaScript function. This function no wr belongs the component to bind it in component constructor. But in order to play with the state of the component you need to pass the component context this. But this is old way, now a days we all use Redux to avoid these old concepts

 export function getItems(this) {
      fetch('./data/data_arr.js')
.then(results => results.json())
.then(results => this.setState({'items': results}));
      }

这样,您可以重用此功能并执行setState。

但是请记住,当您的应用程序将来变得越来越大时,这些解决方案将变得复杂。因此,我建议您从现在开始使用Redux状态管理库,以避免将来出现繁忙的迁移:)

对不起,如果有错字,因为我正在用手机接听电话。

答案 1 :(得分:1)

您需要将上下文传递给您的辅助函数。考虑到您仍在从您的助手中导入功能,在componentDidMount上,可能像这样:

do {
    try AMWorkflow.run(at: url, withInput: nil)
} catch let error {
    print(error)
}

答案 2 :(得分:1)

在抓取方面做得很好,跨组件共享数据可以采用很多路径,您可以查看的两个主要路径是:

  1. 父级状态保存数据,将其通过道具传递
  2. 商店(Mobx,Redux)保存数据,然后根据需要将其注入到组件中

我不会为您提供有关如何全部操作的教程,但我认为第一种选择现在最适合您。

如果您的组件使用相同的数据,则从理论上讲,它们在结构上应具有相同的父组件:

Page Component (Overarching component, lays out the page structure)
 Header
 Component 1
 Component 2
 Footer

因此,您将在Page component的装载上进行此调用,并将this.state.items作为道具传递给需要它的其他组件...商店具有类似的过程,它们只是保存了重复处理道具:)

答案 3 :(得分:0)

由于您正在通过getItems()方法访问/修改状态,因此应将其绑定到构造函数中,如下所示:

constructor() {
    super(props);
    this.state = {
      items : []
    };
    this.getItems = this.getItems.bind(this);
}

或者您可以使用箭头函数简单地声明它,因此不必绑定它:

getItems = () => {
   // some codes here
}

另一件事,唯一可以访问/修改组件状态的是它自己的方法。如果要在自身之外使用它,请将这些组件作为子组件导入组件内,然后将getItems()方法作为prop传递。

  render() {
  return (
    <HashRouter>
      <div className="container">
        // some other codes
        <ChildComponent getItems={this.getItems} />
      </div>
      </HashRouter>
    );
  }