React.js:使用 Fetch API 和对象数组中的道具加载 JSON 数据

Posted

技术标签:

【中文标题】React.js:使用 Fetch API 和对象数组中的道具加载 JSON 数据【英文标题】:React.js: loading JSON data with Fetch API and props from object array 【发布时间】:2016-09-26 15:12:14 【问题描述】:

完全是 react.js 的新手,在完成教程和阅读文档之后,我仍然在使用 js fetch 从 JSON 文件加载我的数据以及从对象数组设置属性方面遇到一些问题。我也不确定我是否在我的事件处理程序中正确访问了 DOM 属性。我一定错过了一些相当简单的东西。

供参考,here's my code with the rest of the project 和 here's what it's supposed to look like.

ETA:我从文档中不知道 babel 浏览器已被弃用,因此决定只使用带有 ES5 语法的直接 javascript 而不是 JSX。下面更新了代码,但它仍然没有呈现标记。

var CanvasAnimation = React.createClass(
    getInitialState: function() 
        return data: [];
    ,                            
    loadData: function() 
        /*
        fetch("data.json")
            .then(function(response) 
                return response.json    
                    .then(function(json)
                        this.setState(data: json);
                    .bind(this))
            .bind(this));
        */
        const data = [
             id: "stalkerOne", width: 225, height: 434, spriteSheetURL: 'spriteSheets/stalkerone.jpg', rows: 5, columns: 5, totalFrames: 24 ,
             id: "stalkerTwo", width: 175, height: 432, spriteSheetURL: 'spriteSheets/stalkertwo.jpg', rows: 6, columns: 5, totalFrames: 26 ,
             id: "stalkerThree", width: 251, height: 432, spriteSheetURL: 'spriteSheets/stalkerthree.jpg', rows: 6, columns: 5, totalFrames: 28 
        ];
    ,
    componentDidMount: function() 
        this.loadData();
    ,
    componentDidUpdate: function() 
        function animation(json) 
            return json.map(function(data) 
                return(
                    new CanvasSprite(
                        document.getElementById(data.id),
                        data.width,
                        data.height,
                        data.spriteSheetURL,
                        data.rows,
                        data.columns,
                        data.totalFrames)
                );
            );
        ;
        this.setState(animaton: animation(this.state.data));  
    ,
    handleInteraction: function(event, index) 
        var offsetY = event.clientY - event.node.getBoundingClientRect().top;
        var relY = offsetY/this.state.data.height;
        this.props.animation[index].setFrame(relY);
    ,
    render: function() 
        var canvases = this.state.data.map(function(data, index) 
            return (
                React.createElement('canvas', 
                                    id = data.id,
                                    width = data.width,
                                    height = data.height,
                                    style = 'border:5px solid white',
                                    onMouseOver= this.handleInteraction(event, index))
            );
        );
        return(
            React.createElement('div', canvases)
        );
    
);
  
    
ReactDOM.render(
    React.createElement(CanvasAnimation, null),
    document.getElementById('content')
); 

【问题讨论】:

您没有在问题中说明问题所在。 虽然this.setState(data: json, animation()); 此处缺少一个键,但您似乎在此处有语法错误? 问题是状态和道具似乎都没有实际设置,并且标记没有呈现。你是说需要预定义密钥(在这种情况下为data)吗?我没有在示例中看到这样做,也没有在文档中引用。 不,我的意思是你在一个对象内部有函数animation(),没有一个不是合法javascript代码的键..你的意思是 data: json, canvas: animation() 。仔细检查后,您的 animation 函数不会返回任何内容 setState(function(previousState, currentProps) ...),我想你提到的代码是这样的。即使这种风格,函数 setState 仍然会改变 this.state 的结果函数作为参数。 【参考方案1】:

您的代码中有大量语法错误,我已为您修复。

const  Component  = React;
const  render  = ReactDOM;

class CanvasAnimation extends Component 
  state = 
    data: []
  ;

  loadData() 
    function animation(json) 
      return json.map(function(data) 
        return (
          new CanvasSprite(
            document.getElementById(data.id),
            data.width,
            data.height,
            data.spriteSheetURL,
            data.rows,
            data.columns,
            data.totalFrames
          )
        );
      );
    
    fetch("data.json")
      .then(response => response.json())
      .then(json => 
        console.log(json);
        this.setState(
          data: json,
          animation: animation(json)
        );
      );
  

  componentDidMount() 
    this.loadData();
  

  handleInteraction(e) 
    var offsetY = e.clientY - e.node.getBoundingClientRect().top;
    var relY = offsetY/this.state.data.height;
    this.props.animation.setFrame(relY);
  

  render() 
    var canvases = this.state.data.map(function(data) 
      return (
        <canvas
          id=data.id 
          width=data.width 
          height=data.height
          style=border: '5px white'
          onMouseOver=this.handleInteraction
        />
      );
    );

    return (
      <div>canvases</div>
    );
  


render(
  <CanvasAnimation />,
  content
);

我不知道你的 API 的响应,所以我不确定是否还有其他需要修复。

我注意到的一些问题:

可能你的缩进是错误的,因为你有带有双 return 语句的函数。我建议你在你的 IDE 中启用 ESLint 来捕捉这些错误。

你还没有理解setState是如何工作的,你不能这样做:

this.setState(
  foo: 'bar',
  baa: myFn(this.state.foo)
);

否则,myFn 中的 this.state.foo 将引用它的旧值,而不是您现在设置的新值。 你必须这样做this.setState(foo: 'bar', () =&gt; this.setState(baa: myFn(this.state.foo)),但是,最好像我在上面修复的代码中那样做。

【讨论】:

问题是我使用了function animation() this.state.data.map() 而不是function animation(json) json.map() ,这更有意义。但这应该只影响道具,而不是状态。我在画布周围设置了边框,这样我就可以判断它们是否至少在渲染,而不管设置的道具如何,而它们不是。 It's not rendering. 你有很多语法错误,不仅仅是动画功能的问题。用 linter 修复所有这些,然后您的页面可能会呈现。 我刚刚粘贴了您的代码。您为回答此问题而编写的代码未呈现。 抱歉,SO 不是您要求编写代码并得到它的地方。我给了你提示和答案来帮助你让你的代码工作。就是这样。 我没有要求任何人为我重写我的代码,但你做到了。您通过重写所有不起作用的代码来回答这个问题,所以如果由于很多语法错误而没有呈现和抛出错误,那么它们就是您的语法错误。这不是问题的答案……只是不同的代码不起作用。所以我想现在我可以选择继续调试我的还是切换到调试你的了?【参考方案2】:

好的...Here's the working project. 得到了@gumingfeng 和@hkal 的帮助。

经验教训:

    React 文档已经过时了。 Straight JS 与 JSX 真的不比 imo 差。 更正了 Fetch 中的一些语法错误。 为了在构造函数中传递 DOM 引用, 数据加载后需要实例化对象数组。 但是,在 componentDidUpdate() 内调用 setState() 会触发无限循环,因此必须直接且独立于状态设置对象数组。 从数组创建 DOM 元素时,React 不会自动将事件处理程序分配给特定元素。换句话说,它必须传递数组索引,以便可以用来访问它在数组中的值。

哇,我想就是这样。希望这对其他人有帮助。

最后我想说的是,在没有 JSX 的情况下试试 React。真的没那么糟糕:)

const  Component  = React;
const  render  = ReactDOM;

class CanvasAnimation extends Component 
    
    constructor()
        super();
        this.state = 
            data: []
        ;
    ;
    
    componentDidMount() 
        fetch("data.json")
            .then( (response) => 
                return response.json() )   
                    .then( (json) => 
                        this.setState(data: json);
                    );
    ;
    
    componentDidUpdate() 
        function animation(json) 
            return json.map( (data) => 
                return(
                    new CanvasSprite(
                        document.getElementById(data.id),
                        data.width,
                        data.height,
                        data.spriteSheetURL,
                        data.rows,
                        data.columns,
                        data.totalFrames)
                );
            );
        ;
        //this.setState(animation: animation(this.state.data)); //causes infinite loop
        this.animation = animation(this.state.data);
    ;
    
    handleInteraction(event, index) 
        var offsetY = event.clientY -  document.getElementById(this.state.data[index].id).getBoundingClientRect().top;
        var relY = offsetY/this.state.data[index].height;
        this.animation[index].setFrame(relY);
    ;
    
    render() 
        var canvases = this.state.data.map( (data, index) => 
            return (
                React.createElement('canvas', 
                                    id : data.id,
                                    width : data.width,
                                    height : data.height,
                                    //style : border: '5px solid white',
                                    onMouseMove : (event) => this.handleInteraction(event, index)
                                    )
            );
        );
        return(
            React.createElement('div', null, ...canvases)
        );
    ;
    
;
  
    
render(
    React.createElement(CanvasAnimation, null),
    document.getElementById('content')
);

【讨论】:

这是对我帮助最大的答案。直接从 componentDidMount() 调用 fetch 解决了未定义的this 挫折

以上是关于React.js:使用 Fetch API 和对象数组中的道具加载 JSON 数据的主要内容,如果未能解决你的问题,请参考以下文章

Fetch API 无法加载“.php”本地文件 - React JS + PHP

如何使用 React.js 中的 Fetch API 将数据发布到数据库

React JS Fetch 返回空响应,但 Postman 没有

在 React JS 中使用 fetch 处理响应状态

无法使用 fetch API 获取数据

React Js API 调用 Jest 测试用例?