【问题标题】:loading json data from local file into React JS将本地文件中的 json 数据加载到 React JS 中
【发布时间】:2015-10-23 20:03:41
【问题描述】:

我有一个 React 组件,我想从文件中加载我的 JSON 数据。控制台日志当前不起作用,即使我将变量 data 创建为全局变量

'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');

任何关于最佳方式的建议,最好是“React”方式,将不胜感激!

【问题讨论】:

  • console.log 工作正常,您只是在调用reqListener 之前调用它。
  • 感谢乔丹的回复。在代码中它出现在 reqListener 之后,所以我不确定我是否理解。能详细点吗?
  • 您的 Ajax 请求需要时间。 JavaScript 在继续下一条指令之前不会等待请求完成(因为请求可能需要几分钟甚至几小时才能完成)。我们称之为“异步”(或有时“非阻塞”)执行。在send() 被调用后,console.log 被立即调用……一段时间后,Ajax 请求完成,reqListener 被调用。如果您希望仅在 Ajax 请求完成后发生某些事情,则必须在 reqListener 中实现该事情。
  • 谢谢乔丹,现在确实有道理。感谢您花时间解释,其他链接有所帮助。我试图将我所有的 React 代码移到 reqListener 中,这样它就可以在回调中工作,但这似乎是个坏主意。有没有办法在运行其余代码之前等待响应?再次感谢。

标签: javascript ajax json xmlhttprequest reactjs


【解决方案1】:

您正在打开一个asynchronous connection,但您编写的代码好像是同步的。 reqListener 回调函数不会与您的代码同步执行(即在React.createClass 之前),但只会在您的整个 sn-p 运行完毕并且从您的远程位置收到响应之后。

除非您处于零延迟的量子纠缠连接上,否则在您的所有语句都运行之后,这是好吧。例如,要记录接收到的数据,您可以:

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

我没有看到在 React 组件中使用 data,所以我只能从理论上提出这个建议:为什么不在回调中更新您的组件?

【讨论】:

  • 非常感谢约翰的帮助。我一直在研究如何在回调中更新组件,但运气不佳。跟国家有关系吗?我还是 React 的新手!我已经更新了代码以显示组件是如何工作的——你能告诉我如何在回调中传递数据吗?再次感谢!
  • @Desmond 是的,状态可以工作,因为当状态改变时,组件会重新渲染。
  • zero-latency quantum-entanglement connection ? 也许是时候发明这些了,这样人们就不必再学习异步了...
【解决方案2】:

使文件对您的组件可用的最简单和最有效的方法是:

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

注意路径前的json!

【讨论】:

  • 除非您为此添加库,否则这将不起作用。因为这在 React 中默认是不支持的。示例库:- npmjs.com/package/json-loader
  • json-loader 包含在较新的 Webpack 版本中,我相信,但您可能仍需要在 Webpack 配置中添加一些内容以使用该确切语法。做一些研究。
  • @agm1984 自 2015 年以来情况发生了变化,如果您提供完整的答案会很好。
  • 我相信最新的 Webpack 版本包含 json-loader 所以你不需要安装它或者在你的配置文件中声明它。我建议尝试import FILE_AS_VARIABLE from './file/location.json'
【解决方案3】:

我试图做同样的事情,这对我有用(ES6/ES2015):

import myData from './data.json';

我在一个反应​​原生线程上从这个答案中得到了解决方案,问同样的事情:https://stackoverflow.com/a/37781882/176002

【讨论】:

  • 如果你在webpack中使用这个方法,你需要json-loader来导入json文件。
  • 谢谢!我一直在寻找一种在 JSX 中访问 json 数据的简单方法,而这正是它!
  • 请注意,这会将您的 JSON 编译到包中,从而无法热交换 JSON 文件。对于很多用例来说,这可能没问题,但它不适合我。
  • 这个答案应该被标记为最准确的答案,但带有json-loader包示例
  • 为我工作。我正在使用汇总。以前有 var data = import(‘./data.json’) 导入了一个 Promise。将此更改为 import data from ‘./data.json’ 可以直接访问导入的对象。
【解决方案4】:
  1. 安装json-loader:
npm i json-loader --save
  1. src中创建data文件夹:
mkdir data
  1. 把你的文件放在那里。

  2. 加载您的文件:

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

【讨论】:

  • A 在不使用 json! 时出现“严重依赖:依赖的请求是表达式”错误。谢谢。
  • 无论如何我可以使用 src 文件夹之外的 .json 文件吗?我正在为我的项目使用 create-react-app
【解决方案5】:

您可以使用 webpack 配置将您的 JSON 文件添加为外部文件。然后,您可以在任何反应模块中加载该 json。

看看this answer

【讨论】:

    【解决方案6】:

    如果您想加载文件,作为应用功能的一部分,那么最好的方法是包含并引用该文件。

    另一种方法是请求文件,并在运行时加载它。这可以通过FileAPI 完成。还有另一个关于使用它的 StackOverflow 答案: How to open a local disk file with 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>
        );
      }
    }
    

    【讨论】:

      【解决方案7】:

      如果你有几个 json 文件:

      import data from 'sample.json';
      

      如果您要动态加载多个 json 文件之一,您可能必须改用 fetch

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

      【讨论】:

        【解决方案8】:

        我的 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>
                          
        

        【讨论】:

        • 添加代码很好,但你需要用 cmets 解释你的代码。
        • 是的!但我简短地解释一下。下次我将尝试添加带有解释的代码。谢谢
        猜你喜欢
        • 2020-09-23
        • 1970-01-01
        • 2013-01-07
        • 2021-07-16
        • 1970-01-01
        • 2018-07-11
        • 2016-04-08
        • 2018-04-11
        相关资源
        最近更新 更多