Javascript React.js:使用 Fetch API 和对象数组中的道具加载 JSON 数据
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/37497711/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
React.js: loading JSON data with Fetch API and props from object array
提问by Sophia Gold
Totally new to react.js and after going through the tutorial and reading the docs, I'm still struggling a bit with using js fetch to load my data from a JSON file as well as setting properties from an array of objects. I'm also not certain I'm accessing DOM properties correctly in my event handler. I must be missing something rather straightforward.
对 react.js 完全陌生,在完成教程和阅读文档后,我仍然在使用 js fetch 从 JSON 文件加载我的数据以及从对象数组设置属性方面遇到了一些困难。我也不确定我是否在我的事件处理程序中正确访问了 DOM 属性。我一定错过了一些相当简单的东西。
For reference, here's my code with the rest of the projectand here's what it's supposed to look like.
作为参考,这里是我的代码与项目的其余部分和这里就是它应该的样子。
ETA: I had no idea from the docs that babel browser was deprecated so decided to just use straight Javascript with ES5 syntax instead of JSX. Code updated below, but it's still not rendering the markup.
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')
);
采纳答案by Sophia Gold
Ok... Here's the working project.Got some help from @gumingfeng and @hkal.
好的...这是工作项目。从@gumingfeng 和@hkal 那里得到了一些帮助。
Lessons learned:
得到教训:
- The React docs are ridiculously outdated.
- Straight JS vs. JSX is really no worse imo.
- Corrected some syntax errors in Fetch.
- Object array needs to be instantiated afterdata is loaded in order to pass DOM references in the constructors.
- However, calling
setState()
insidecomponentDidUpdate()
triggers an infinite loop so had to set the object array directly and independently from state. - When creating DOM elements from an array, React does not automatically assign the event handler to the particular element. In other words, it must be passed the array index so that can be used to access its values in the arrays.
- React 文档已经过时了。
- Straight JS vs. JSX 真的没有更糟糕的 imo。
- 更正了 Fetch 中的一些语法错误。
- 对象数组需要在数据加载后实例化,以便在构造函数中传递 DOM 引用。
- 但是,调用
setState()
内部componentDidUpdate()
会触发无限循环,因此必须直接且独立于状态设置对象数组。 - 从数组创建 DOM 元素时,React 不会自动将事件处理程序分配给特定元素。换句话说,它必须传递数组索引,以便可以用来访问它在数组中的值。
Whew, I think that's it. Hope this helps others.
哇,我想就是这样。希望这对其他人有帮助。
And I would just conclude by saying, give React a try without JSX. It's really not that bad :)
最后我只想说,在没有 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')
);
回答by Fez Vrasta
You have tons of syntax errors in your code, I have fixed them for you.
您的代码中有大量语法错误,我已经为您修复了它们。
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
);
I don't know the response of your API so I'm not sure if there's other to fix.
我不知道您的 API 的响应,所以我不确定是否还有其他问题需要修复。
Some of the problems I have noticed:
我注意到的一些问题:
Probably your indentation is wrong, because you had functions with double
return
statements. I suggest you to enable ESLint in your IDE to catch those errors.You have not understood how
setState
works, you can't just do:this.setState({ foo: 'bar', baa: myFn(this.state.foo) });
Otherwise,
this.state.foo
insidemyFn
will refer to the old value of it, and not to the new one that you are setting right now.
You'd have to dothis.setState({foo: 'bar'}, () => this.setState({baa: myFn(this.state.foo)})
, but then, it's better to do as I did in the code I have fixed above.
可能你的缩进是错误的,因为你有带有双
return
语句的函数。我建议您在 IDE 中启用 ESLint 以捕获这些错误。你还没有理解它是如何
setState
工作的,你不能只做:this.setState({ foo: 'bar', baa: myFn(this.state.foo) });
否则,
this.state.foo
insidemyFn
将引用它的旧值,而不是您现在正在设置的新值。
你必须这样做this.setState({foo: 'bar'}, () => this.setState({baa: myFn(this.state.foo)})
,但是,最好像我在上面修复的代码中所做的那样做。