React.js:使用Fetch API加载JSON数据,并从对象数组中加载道具

时间:2016-05-28 10:10:00

标签: javascript json reactjs fetch

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

供参考,here's my code with the rest of the projecthere'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')
); 




2 个答案:

答案 0 :(得分:23)

您的代码中存在大量语法错误,我已经为您修复了这些错误。

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

    否则,this.state.foo内的myFn将引用它的旧值,而不是您现在正在设置的新值。
    您必须this.setState({foo: 'bar'}, () => this.setState({baa: myFn(this.state.foo)}),但是,我在上面修复的代码中做得更好。

答案 1 :(得分:14)

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

经验教训:

  1. React文档过时了。
  2. Straight JS vs. JSX真的不差了。
  3. 更正了Fetch中的一些语法错误。
  4. 在加载数据之后,需要对对象数组进行实例化,以便在构造函数中传递DOM引用。
  5. 但是,在setState()内调用componentDidUpdate()会触发无限循环,因此必须直接设置对象数组并独立于状态。
  6. 从数组创建DOM元素时,React不会自动将事件处理程序分配给特定元素。换句话说,它必须传递给数组索引,以便可以用来访问数组中的值。
  7. 哇,我想是的。希望这有助于其他人。

    我最后会说,给React一个没有JSX的尝试。这真的不是那么糟糕:))

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