завантаження даних JSON з локального файлу в React JS


78

У мене є компонент React, і я хочу завантажити свої дані JSON із файлу. На даний момент журнал консолі не працює, хоча я створюю дані змінних як глобальні

'use strict';

var React = require('react/addons');

// load in JSON data from file
var data;

var oReq = new XMLHttpRequest();
oReq.onload = reqListener;
oReq.open("get", "data.json", true);
oReq.send();

function reqListener(e) {
    data = JSON.parse(this.responseText);
}
console.log(data);

var List = React.createClass({
  getInitialState: function() {
    return {data: this.props.data};    
  },
  render: function() {
    var listItems = this.state.data.map(function(item) {
        var eachItem = item.works.work;        

        var photo = eachItem.map(function(url) {
            return (
                <td>{url.urls}</td> 
            )
        });
    });
    return <ul>{listItems}</ul>
  }
});

var redBubble = React.createClass({
    render: function() {
      return (
        <div>
          <List data={data}/>          
        </div>
      );
    }
  });

module.exports = redBubble;

В ідеалі, я би віддав перевагу зробити щось подібне, але це не працює - він намагається додати ".js" в кінець імені файлу.

var data = require('./data.json');

Будемо дуже вдячні за будь-які поради щодо найкращого способу, бажано "Реагування"!


1
Все console.logпрацює чудово, ви просто телефонуєте до того, reqListenerяк коли-небудь буде викликано.
Йорданія, біг

Дякую за відповідь Йорданія. У коді він надходить після reqListener, тому я не впевнений, що розумію. Не могли б ви розказати, будь ласка?
Десмонд

1
Ваш запит Ajax вимагає часу. JavaScript не чекає закінчення запиту, перш ніж переходити до наступної інструкції (оскільки запит може зайняти хвилини або навіть години). Ми називаємо це "асинхронним" (або іноді "неблокуючим") виконанням. Відразу після send()викликається, console.logвикликається ... а через деякий час запит Ajax закінчується і reqListenerвикликається. Якщо ви хочете, щоб щось сталося лише після завершення запиту Ajax, ви повинні зробити так, щоб це сталося в reqListener.
Йорданія, біг


Дякуємо Йорданії, це зараз має сенс. Дякуємо, що знайшли час пояснити, і інше посилання допомогло. Я спробував перемістити весь мій код React усередину reqListener, тому він би працював у зворотному виклику, але це здається поганою ідеєю. Чи можна зачекати на відповідь, перш ніж запустити решту коду? Знову дякую.
Десмонд

Відповіді:


16

Ви відкриваєте асинхронне з'єднання , але ви написали свій код так, ніби він був синхронним. Функція reqListenerзворотного виклику не буде виконуватися синхронно з вашим кодом (тобто раніше React.createClass), а лише після того, як запуститься весь ваш фрагмент і відповідь буде отримана з вашого віддаленого місця.

Якщо у вас немає з'єднання з квантовою заплутаністю з нульовою затримкою, це станеться після того, як усі ваші твердження будуть запущені. Наприклад, для реєстрації отриманих даних потрібно:

function reqListener(e) {
    data = JSON.parse(this.responseText);
    console.log(data);
}

Я не бачу використання dataкомпонента React, тому можу лише запропонувати це теоретично: чому б не оновити ваш компонент у зворотному виклику?


Велике спасибі за допомогу, Джон. Я розглядав, як оновити компонент зворотного виклику, але не маючи великої удачі. Це пов’язано з державою? Я все ще новачок у React! Я оновив код, щоб показати, як працює компонент - чи можете ви сказати мені, як передавати дані при зворотному виклику? Знову дякую!
Десмонд

@Desmond Так, стан може працювати, оскільки компонент буде відтворений, коли його стан зміниться.
Джон Вайс

4
zero-latency quantum-entanglement connection😂 можливо, настав час їх вигадувати, щоб людям більше не довелося дізнаватися про асинхронізацію ...
ssc

142

Я намагався зробити те саме, і ось що мені вдалося (ES6 / ES2015):

import myData from './data.json';

Я отримав рішення з цієї відповіді в реакційному потоці, який запитує те саме: https://stackoverflow.com/a/37781882/176002


11
Якщо ви використовуєте цей метод із webpack, вам потрібен json-loader для імпортованих файлів json.
kevr

3
Дякую! Я шукав простий спосіб отримати доступ до даних JSON в JSX, і це саме він!
Matt Brand

6
Зауважте, що це скомпілює ваш JSON у комплект, унеможливлюючи гарячу заміну файлів JSON. Це, мабуть, добре для багатьох випадків використання, але це не стосувалося мого.
Вільсон Біггс,

цю відповідь слід позначити як найбільш точну відповідь, але на json-loaderприкладі пакета
Syed Aqeel,

Працював у мене. Я використовую зведення. Раніше було var data = import(‘./data.json’)яке імпортувало Promise. Змінивши це, import data from ‘./data.json’надали прямий доступ до імпортованого об’єкта.
Макс Маклауд,

25

Найпростіший та найефективніший спосіб зробити файл доступним для вашого компонента:

var data = require('json!./data.json');

Зверніть увагу json!на шлях до шляху


3
Це не буде працювати, якщо ви не додасте для цього бібліотеку. Оскільки це не підтримується за замовчуванням у React. приклад бібліотеки: - npmjs.com/package/json-loader
Gopinath Langote

2
json-loaderя вважаю, що ця версія включена в новіші версії Webpack, але вам все одно доведеться додати щось до конфігурації Webpack, щоб використовувати саме такий синтаксис. Проведіть це дослідження.
agm1984

@ agm1984 речі змінилися з 2015 року, було б непогано, якщо б ви надали повну відповідь
César D. Velandia

1
Я вважаю, що найновіші версії Webpack містять json-loader, тому вам не потрібно його встановлювати або оголошувати у своєму конфігураційному файлі. Я б рекомендував спробувати простоimport FILE_AS_VARIABLE from './file/location.json'
agm1984

Дивіться відповідь тут: stackoverflow.com/questions/43735486 / ...
agm1984

11
  1. встановити json-loader:

    npm i json-loader --save

  2. створити dataпапку в src:

    mkdir data

  3. покладіть туди свої файли

  4. завантажте файл

    var data = require('json!../data/yourfile.json');


A мала помилку "Критична залежність: запит залежності є виразом", коли НЕ використовується json!. Дякую.
secavfr

1
чи є в будь-якому випадку я можу використовувати файл .json поза папкою src? Я використовую створити реагує-додаток для мого проекту
Chamod Патхірана

9

Якщо у вас є кілька файлів json:

import data from 'sample.json';

Якщо вам потрібно було динамічно завантажувати один із багатьох файлів json, можливо, вам доведеться використовувати fetchзамість:

fetch(`${fileName}.json`)
  .then(response => response.json())
  .then(data => console.log(data))

3

Ім'я мого файлу JSON: terrifcalculatordata.json

[
    {
      "id": 1,
      "name": "Vigo",
      "picture": "./static/images/vigo.png",
      "charges": "PKR 100 per excess km"
    },
    {
      "id": 2,
      "name": "Mercedes",
      "picture": "./static/images/Marcedes.jpg",
      "charges": "PKR 200 per excess km"
    },
    {
        "id": 3,
        "name": "Lexus",
        "picture": "./static/images/Lexus.jpg",
        "charges": "PKR 150 per excess km"
      }
]

Спочатку імпортуйте зверху:

import calculatorData from "../static/data/terrifcalculatordata.json";

то після повернення:

  <div>
  {
    calculatorData.map((calculatedata, index) => {
        return (
            <div key={index}>
                <img
                    src={calculatedata.picture}
                    class="d-block"
                    height="170"
                />
                <p>
                    {calculatedata.charges}
                </p>
            </div>
                  

1

Ви можете додати свій файл JSON як зовнішній за допомогою конфігурації webpack. Потім ви можете завантажити цей json в будь-який з ваших модулів реагування.

Погляньте на цю відповідь


0

Якщо ви хочете завантажити файл, як частину функціональних можливостей вашого додатка, найкращим підходом буде включення та посилання на цей файл.

Інший підхід - запитувати файл і завантажувати його під час виконання. Це можна зробити за допомогою FileAPI . Існує також інша відповідь StackOverflow щодо його використання: Як відкрити файл локального диска за допомогою Javascript?

Я включу трохи модифіковану версію для використання в React:

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      data: null
    };
    this.handleFileSelect = this.handleFileSelect.bind(this);
  }

  displayData(content) {
    this.setState({data: content});
  }

  handleFileSelect(evt) {
    let files = evt.target.files;
    if (!files.length) {
      alert('No file select');
      return;
    }
    let file = files[0];
    let that = this;
    let reader = new FileReader();
    reader.onload = function(e) {
      that.displayData(e.target.result);
    };
    reader.readAsText(file);
  }

  render() {
    const data = this.state.data;
    return (
      <div>
        <input type="file" onChange={this.handleFileSelect}/>
        { data && <p> {data} </p> }
      </div>
    );
  }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.