编辑:经过进一步测试,我意识到componentDidMount的行为符合我的预期,但是我的随机化函数似乎存在问题,由于某种原因,如果第二次运行该函数,它将返回undefined,所以在初始挂载它给我结果,当我再次挂载它时返回未定义,因此没有渲染...
我已经进行了研究,以了解为什么会有这个问题。我有一个用于webapp的组件,它只是一个横幅,将显示赞助商名称。每次渲染此横幅时,我都希望将赞助者出现的顺序随机化。我可以使它正常工作,但这只是在它第一次被渲染时发生(在componentDidMount()上),然后每次我访问该组件被渲染的任何部分时,它都不再调用componentDidMount(),因此它不渲染任何内容。
起初,我认为每当我进入一个正在调用该组件的部分时,都应该调用componentDidMount()。阅读后,到处都说该组件已被安装一次,这就是为什么它只调用一次函数的原因。如何使它在每次渲染组件时随机化?
这是我正在编写的代码示例。
class SponsorBanner extends React.Component {
constructor(props){
super(props)
this.state = {
randomized: []
}
this.randomizeSponsors = this.randomizeSponsors.bind(this)
}
randomizeSponsors(){
let copy = []
const array = ['a','b','c','d']
let n = array.length
let i;
while(n){
i = Math.floor(Math.random() * n--)
copy.push(array.splice(i,1)[0])
}
let randomizedArray = copy.map((sponsor,i) => <div key={i}>{sponsor}</div>)
this.setState({randomized:randomizedArray})
}
componentDidMount(){
this.randomizeSponsors()
}
render(){
return (
<div>
{this.state.randomized}
</div>
)
}
}
此组件在应用程序的2个不同部分中呈现。这是一个非常简单的应用程序,我什至不添加路由。它只是完全用作SPA。用户单击部分时,它将呈现该组件。第一次加载时,如果我访问呈现此组件的部分,它将显示一个随机数组。如果我导航到另一部分并返回,它将呈现一个空白横幅。
为什么会这样,我该如何解决?
答案 0 :(得分:2)
另一种方法可能是使用setIterval
,如果您希望它每x量更改milliseconds
。
工作示例:https://codesandbox.io/s/k9zz9wq9lo
import random from "lodash/random";
import React, { Component } from "react";
export default class Banner extends Component {
state = {
randomIndex: 0
};
componentDidMount = () => this.setTimer();
componentWillUnmount = () => this.clearTimer();
clearTimer = () => clearInterval(this.timeout);
timer = () => this.setState({ randomIndex: random(0, 999) });
setTimer = () => (this.timeout = setInterval(this.timer, 3000));
render = () => (
<img
src={`https://loremflickr.com/600/100?lock=${this.state.randomIndex}`}
/>
);
}
或者,如果您不想使用setIterval
并且该组件始终处于挂载状态,并且只希望在状态更改时进行更改,则可以使用HOC
组件管理状态。然后,您可以利用HOC
的{{1}}方法来更新变量。
工作示例:https://codesandbox.io/s/6qvl49vqw
render
答案 1 :(得分:1)
如果您希望在每次render
调用中随机分配数字,请将该逻辑添加到您的render
函数中:
render() {
const randomized = this.randomizeSponsors(); // IMPORTANT: CHANGE THIS TO MAKE IT RETURN ARRAY INSTEAD OF SETSTATE
return (
<div>
{randomized}
</div>
);
}