Javascript 从映射函数渲染一系列图像时遇到问题
我正在尝试设计一个组件,用户可以单击一个按钮,该按钮将触发giphy API调用,最终呈现一系列gif图像 到目前为止,我能够成功地完成所有工作,除了实际的图像渲染。以下是我目前的代码:Javascript 从映射函数渲染一系列图像时遇到问题,javascript,reactjs,rendering,Javascript,Reactjs,Rendering,我正在尝试设计一个组件,用户可以单击一个按钮,该按钮将触发giphy API调用,最终呈现一系列gif图像 到目前为止,我能够成功地完成所有工作,除了实际的图像渲染。以下是我目前的代码: retrieveURLs() { *bunch of stuff to make API call and return an array of URLs related to the category of the button the user pushes* } renderGifs(
retrieveURLs() {
*bunch of stuff to make API call and return an array of URLs related
to the category of the button the user pushes*
}
renderGifs() {
this.retrieveURLs().then(function(results) {
console.log(results); //logs array of URLs
return results.map(function(url, index) {
console.log(url); //logs each url
return (<img key={index} src={url} alt="" />)
}, this);
});
}
render() {
return(
<div id="gif-div">
{this.renderGifs()}
</div>
)
}
retrieveURLs(){
*进行API调用并返回相关URL数组的一堆东西
到用户按下的按钮的类别*
}
renderGifs(){
this.retrieveURLs().then(函数(结果){
console.log(results);//记录URL数组
返回results.map(函数(url、索引){
console.log(url);//记录每个url
返回()
},这个);
});
}
render(){
返回(
{this.renderGifs()}
)
}
尽管每个console.log()事件都指示URL至少被正确传递,但不会呈现任何内容
我对父组件执行了类似的操作,从一组类别中渲染按钮,如下所示:
btnArray = [*bunch of categories here*];
renderButtons() {
return btnArray.map(function(item, i) {
let btnID = btnArray[i].replace(/\s+/g, "+");
return <button type='button' className="btn btn-info" onClick={this.handleCategorySelect} key={i} id={btnID} value={btnID}>{btnArray[i]}</button>
}, this)
}
btnArray=[*这里有一堆类别*];
renderButtons(){
返回btnArray.map(函数(项,i){
设btnID=btnArray[i]。替换(/\s+/g,“+”);
返回{btnArray[i]}
},本页)
}
按钮已正确渲染,但我的图像未正确渲染。renderbuttons和rendergifs metohds都不会改变状态。老实说,我看不出两者之间有什么有意义的区别,所以我希望能得到一些帮助,弄清楚为什么一个有效,而另一个无效 首先,您忘记了返回语句:
renderGifs() {
return this.retrieveURLs().then(function(results) {
...
}
但这并不能解决任何问题,因为它返回了一个承诺
您需要将请求结果保存在状态中,然后将其映射:
constructor(props){
super(props);
this.state = { images: [] };
}
componentDidMount() {
this.renderGifs();
}
renderGifs() {
this.retrieveURLs().then(function(results) {
console.log(results); //logs array of URLs
this.stateState({ images: results });
});
}
render() {
return(
<div id="gif-div">
{
this.state.images.map((url, index) => (<img key={index} src={url} alt="" />);
}
</div>
)
}
构造函数(道具){
超级(道具);
this.state={images:[]};
}
componentDidMount(){
这个.renderGifs();
}
renderGifs(){
this.retrieveURLs().then(函数(结果){
console.log(results);//记录URL数组
this.stateState({images:results});
});
}
render(){
返回(
{
this.state.images.map((url,索引)=>();
}
)
}
问题在于图像的渲染功能以及React在上一个和当前状态之间的方式不同。由于提取是异步的,而渲染不是异步的,因此在提取完成时React不知道它需要重新渲染组件。在这种情况下,有一些方法可以强制重新渲染,但更好的方法是解决方案是使用shouldUpdate
检查中已经包含的功能
您的实现可能会更改为如下所示:
class Images extends Component {
state = {
images: [],
error: null
}
componentDidMount() {
return this.retrieveImages()
.then(images => this.setState({images}))
.catch(error => this.setState({error}))
}
... rest of your class definition
render () {
return (
<div>
{this.state.images.map(image => <img src={image.url} />)}
</div>
)
}
}
类图像扩展组件{
状态={
图像:[],
错误:null
}
componentDidMount(){
返回此。retrieveImages()
.then(images=>this.setState({images}))
.catch(error=>this.setState({error}))
}
…类定义的其余部分
渲染(){
返回(
{this.state.images.map(image=>)}
)
}
}
我也会处理一些不好的结果、缺少键/值等。如果不让我知道,我希望这对您有用!:)这是异步函数的本质;不能从回调中返回值到原始调用站点。如果你要写:
const res = this.retrieveURLs().then(function(results) {
return results;
});
您只会更改承诺的分辨率值res
不会被分配结果的值,而是被分配由this.retrieveURLs()
创建的承诺,检索已解析承诺的值的唯一方法是附加。然后
回调
你能做的是:
this.retrieveURLs().then(results => {
this.setState({ images: results });
});
现在,内部状态将异步更新,组件将被告知使用新数据重新渲染,您可以通过访问状态在渲染函数中使用新数据
注意:在上面的示例中,我使用一个arrow函数来创建回调,因为否则这个
将不会绑定到正确的上下文。或者,您可以执行旧的即=此
技巧,或者使用函数#bind
您确定这些img
标记未在页面中呈现吗?可能url是空的或错误的…是的。没有向应该嵌套图像的div元素内的页面呈现任何内容。是的,即使承诺本身是从renderGifs
返回的,React也不支持呈现承诺(尽管这很有趣)。完全未经测试,但不知道是否可以执行类似于``async render()的操作{return({await renderImages()}}``而不破坏内容。看起来像是声明async render(){…}
在React中导致了一个不变的冲突,但这是一个很好的尝试。:-)它确实有帮助,所以谢谢你。你的答案的核心澄清了我需要知道的内容。但是,我不能完全按原样实现你的代码,因为组件呈现时没有主题(retrieveURLs()通过父组件中的let subject=this.props.category
,定义API调用的主题,该主题在用户按下按钮之前是未定义的,因此componentDidMount将始终返回错误(除非我误解了什么)。因此,如果我理解正确,1)renderButtons()方法之所以工作,是因为它依赖于在呈现组件时已定义的数组(并且独立于状态),但renderGifs()方法不工作,因为它依赖于来自状态(this.state.category)的API调用的结果。2)因此,一旦(category)状态已更改,组件已呈现,承诺对状态(以及组件)没有影响。对吗?renderButtons
工作,因为它同步地将JSX返回到render