Реакция Повторное использование данных JSON для всех компонентов - PullRequest
0 голосов
/ 26 сентября 2018

Привет, я новичок в 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 голосов
/ 26 сентября 2018

Две вещи, которые вам нужно знать, когда вы хотите повторно использовать данные вместо того, чтобы снова и снова вызывать fetch

  1. Делать выборку в самом верхнем компоненте, т.е. родительском компоненте, и передавать данныедля всех детей, от детей к детям, но, помните, это будет беспокойно для вас.Этот подход хорош, когда вы создаете небольшое приложение, которое будет максимально от 50 до 50 компонентов.Но когда ваше приложение расширяется, это не рекомендуемый способ повторного использования данных между компонентами.

  2. Используйте библиотеку управления состоянием Redux для повторного использования данных между компонентами.Это действует как централизованный магазин для вашего приложения.В наши дни это используется в основном в каждом приложении React.С помощью Redux вы можете сделать вызов действия в родительском компоненте, и это действие фактически извлечет данные и передаст их редуктору.Теперь редуктор установит данные в хранилище Redux.Теперь данные доступны в каждом компоненте, получая данные из хранилища Redux с помощью state.get.Таким образом, вы можете вызвать избыточное действие, например this.props.getItems ();где бы вам ни понадобились данные в компоненте, а компонент mapStateToProps сделает эти данные доступными для вашего компонента в качестве реквизита

Как получить данные из хранилища Redux?

Определитьфункция mapStateToProps в компоненте и получение данных из хранилища Redux с помощью state.get и возврат их в функцию.Передайте mapStateToProps для подключения метода.Вы будете подключать ваш компонент к компоненту 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, чтобы избежать беспокойной миграции в будущем:)

Извините, если есть какие-либо опечатки, потому что я отвечаю со своего мобильного телефона.

0 голосов
/ 26 сентября 2018

Так что хорошая работа с извлечением, есть много путей, которыми вы можете воспользоваться при совместном использовании данных между компонентами, два основных, на которые вы можете посмотреть:

  1. Родительское состояние содержит данные,пропускает их через реквизит
  2. Магазин (Mobx, Redux) хранит данные, и вы вводите их в свои компоненты по мере необходимости

Я не собираюсь давать вам учебник покак сделать их все, но я предполагаю, что первый вариант будет лучшим для вас прямо сейчас.

Если ваши компоненты используют одни и те же данные, теоретически они должны иметь один и тот же родительский компонент в структуре, подобной этой:

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

Таким образом, вы выполните этот вызов при монтировании Page component и передадите this.state.items в качестве опоры другим компонентам, которые в этом нуждаются ... Магазины имеют аналогичный процесс, который они просто сохраняютдвойная обработка реквизита:)

0 голосов
/ 26 сентября 2018

Поскольку вы получаете доступ / изменяете состояние в своем методе 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>
    );
  }
0 голосов
/ 26 сентября 2018

Вам нужно передать контекст вашей вспомогательной функции.Учитывая, что вы все еще импортируете функцию из вашего помощника, в вашем componentDidMount она может быть такой:

componentDidMount(){
 getItems.call(this);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...