React.js:使用 Fetch API 加载 JSON 数据并从对象数组中获取属性
React.js: loading JSON data with Fetch API and props from object array
完全是 react.js 的新手,在完成教程和阅读文档后,我仍然对使用 js fetch 从 JSON 文件加载数据以及从对象数组设置属性。我也不确定我是否在我的事件处理程序中正确访问 DOM 属性。我一定是遗漏了一些相当简单的东西。
供参考,here's my code with the rest of the project and here's what it's supposed to look like.
ETA:我从文档中不知道 babel 浏览器已被弃用,所以决定直接使用 Javascript 和 ES5 语法而不是 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')
);
您的代码中有大量语法错误,我已为您修复。
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'}, () => this.setState({baa: myFn(this.state.foo)})
,但是,最好像我在上面修复的代码中那样做。
好的... Here's the working project. 从@gumingfeng 和@hkal 那里得到了一些帮助。
经验教训:
- React 文档已经过时得离谱。
- 在我看来,直接 JS 与 JSX 并不差。
- 更正了 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')
);
完全是 react.js 的新手,在完成教程和阅读文档后,我仍然对使用 js fetch 从 JSON 文件加载数据以及从对象数组设置属性。我也不确定我是否在我的事件处理程序中正确访问 DOM 属性。我一定是遗漏了一些相当简单的东西。
供参考,here's my code with the rest of the project and here's what it's supposed to look like.
ETA:我从文档中不知道 babel 浏览器已被弃用,所以决定直接使用 Javascript 和 ES5 语法而不是 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')
);
您的代码中有大量语法错误,我已为您修复。
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'}, () => this.setState({baa: myFn(this.state.foo)})
,但是,最好像我在上面修复的代码中那样做。
好的... Here's the working project. 从@gumingfeng 和@hkal 那里得到了一些帮助。
经验教训:
- React 文档已经过时得离谱。
- 在我看来,直接 JS 与 JSX 并不差。
- 更正了 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')
);