admin管理员组文章数量:1390756
EDIT: Upon further testing i realized that ponentDidMount IS behaving how i was expecting, but it seems to be a problem with my randomizing function that for some reason returns undefined if it gets run a second time, so on initial mount it gives me results, when i mount it again it returns undefined and hence nothing renders...
I have done research to understand why I am having this issue. I have a ponent for a webapp, which is just a banner that will render Sponsor names. Everytime this banner gets rendered I want to randomize the order in which sponsors appear. I can get this to work, but it is only happening the first time it gets rendered (on ponentDidMount()) and then every time i visit any section where that ponent gets rendered it no longer calls ponentDidMount() so it renders no content.
At first i thought ponentDidMount() should be called everytime i enter a section that is calling that ponent. After reading around, everywhere said that the ponent is being mounted once and that is why it is only calling the function once. How can I make it so it randomizes everytime I render the ponent?
Here is sample of the code I'm writing.
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})
}
ponentDidMount(){
this.randomizeSponsors()
}
render(){
return (
<div>
{this.state.randomized}
</div>
)
}
}
This ponent gets rendered in 2 different sections of the app. It is a very simple app and I am not even adding routing to it. It just works entirely as a SPA. When a user click a section, it renders that ponent. On first load if I visit a section that renders this ponent it displays a randomized array. If I navigate to another section and back, it renders an empty banner.
Why is this happening and how could I work around it???
EDIT: Upon further testing i realized that ponentDidMount IS behaving how i was expecting, but it seems to be a problem with my randomizing function that for some reason returns undefined if it gets run a second time, so on initial mount it gives me results, when i mount it again it returns undefined and hence nothing renders...
I have done research to understand why I am having this issue. I have a ponent for a webapp, which is just a banner that will render Sponsor names. Everytime this banner gets rendered I want to randomize the order in which sponsors appear. I can get this to work, but it is only happening the first time it gets rendered (on ponentDidMount()) and then every time i visit any section where that ponent gets rendered it no longer calls ponentDidMount() so it renders no content.
At first i thought ponentDidMount() should be called everytime i enter a section that is calling that ponent. After reading around, everywhere said that the ponent is being mounted once and that is why it is only calling the function once. How can I make it so it randomizes everytime I render the ponent?
Here is sample of the code I'm writing.
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})
}
ponentDidMount(){
this.randomizeSponsors()
}
render(){
return (
<div>
{this.state.randomized}
</div>
)
}
}
This ponent gets rendered in 2 different sections of the app. It is a very simple app and I am not even adding routing to it. It just works entirely as a SPA. When a user click a section, it renders that ponent. On first load if I visit a section that renders this ponent it displays a randomized array. If I navigate to another section and back, it renders an empty banner.
Why is this happening and how could I work around it???
Share Improve this question edited Sep 27, 2018 at 3:54 HoldOffHunger 21k11 gold badges120 silver badges146 bronze badges asked Sep 26, 2018 at 23:52 xunuxxunux 1,7795 gold badges22 silver badges42 bronze badges 6- Why are you storing the random values in the state in the first place? Is there are situation you do not want it to change? – Felix Kling Commented Sep 27, 2018 at 0:02
- hmm no im used to, in other cases, save it in state from within my function so i can render the state and that way when it changes it will render the change. Thats usually for fetch calls though, so it may not be necessary in this case. – xunux Commented Sep 27, 2018 at 0:09
-
are you using react-router? Maybe you could look into
withRouter
andponentDidUpdate
– bozdoz Commented Sep 27, 2018 at 1:06 - hey @bozdoz no im not using react-router or any routing in this particular app since it's very simple and has only 3 sections that are basically working like tabs – xunux Commented Sep 27, 2018 at 1:23
- 1 @xunux just saying: the ponent will need to know when you want something to change. Maybe look into react context api? I wouldn't think you should use redux. if the ponent is a child of the tabs, you could pass a unique prop to alter it... just trying to help you think of a way to achieve this. Good luck. – bozdoz Commented Sep 27, 2018 at 2:05
2 Answers
Reset to default 2Another approach could be to use asetIterval
if you want it to change every x amount of milliseconds
.
Working example: https://codesandbox.io/s/k9zz9wq9lo
import random from "lodash/random";
import React, { Component } from "react";
export default class Banner extends Component {
state = {
randomIndex: 0
};
ponentDidMount = () => this.setTimer();
ponentWillUnmount = () => 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./600/100?lock=${this.state.randomIndex}`}
/>
);
}
Or, if you don't want to use a setIterval
and this ponent is always mounted... and you only want it to change when state changes... then have a HOC
ponent manage state. You can then utilize the HOC
's render
method to update a variable.
Working Example: https://codesandbox.io/s/6qvl49vqw
import random from "lodash/random";
import React, { Component } from "react";
import Sample from "./Sample";
export default class Parent extends Component {
state = {
loadC1: false
};
shouldComponentUpdate = (nextProps, nextState) =>
this.state.loadC1 !== nextState.loadC1;
handleClick = () =>
this.setState(prevState => ({ loadC1: !this.state.loadC1 }));
render = () => {
const randomIndex = random(0, 999);
const { loadC1 } = this.state;
return (
<div style={{ textAlign: "center" }}>
<button
className="uk-button uk-button-primary"
onClick={this.handleClick}
>
{!loadC1 ? "Show" : "Hide"} Component
</button>
<div style={{ marginBottom: 40 }}>
{loadC1 && <Sample />}
</div>
<img src={`https://loremflickr./600/100?lock=${randomIndex}`} />
</div>
);
};
}
If you want to have the numbers randomized on each render
call, add that logic into your render
function:
render() {
const randomized = this.randomizeSponsors(); // IMPORTANT: CHANGE THIS TO MAKE IT RETURN ARRAY INSTEAD OF SETSTATE
return (
<div>
{randomized}
</div>
);
}
本文标签:
版权声明:本文标题:javascript - Calling a function each time a component is rendered, since componentDidMount() only triggers once - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744713132a2621245.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论