Reputation: 4368
How I think/understood was that react components update whenever their props or state change.
So I declare my variable:
let percentage = {
width: '10%',
};
and have a setInterval
function running to change that variable after so long:
setInterval(function() {
percentage = {
width: '50%',
};
}, 5000);
and below this I render my component:
Meteor.startup(() => {
render((
<Router>
<div>
<Nav />
<Route exact path="/" render={() => <Start percentage={percentage} />} />
<Route path="/app" component={App} />
<Modal />
</div>
</Router>
), document.getElementById('render-target'));
});
Where I display the percentage in another file that looks like:
export default class Start extends Component {
render() {
return (
<div className="home">
<div className="meter orange">
<span style={this.props.percentage} />
</div>
</div>
);
}
}
My component never updates though, I have put a console.log
into the setInterval
function and get the update variable back but it never refreshes my component.
Have I misunderstood how props updates work?
Upvotes: 2
Views: 825
Reputation: 27292
The parameters passed to a component are copied by value, not reference. So when you render the outermost component, you're passing the current value of percentage
into the Start
component:
<Start percentage={percentage} />
From the perspective of the Start
component, its property never changes, even though the variable that provided its initial value is.
You can't be clever and try to get around this with an object that contains a property percentage
either...because the object (the parameter itself) won't change, only its properties.
So what's a poor programmer to do?
It's a bit misleading to say that a component updates when its properties change; components actually update when they're re-rendered. Very often, this happens because the enclosing (parent) component's state changes (or its been re-rendered) and it will be passing new props down to the inner component. The solution in your case is to make percentage
part of the state of the enclosing component. So you would have something like this:
class Parent extends Component {
constructor(props, ...args) {
super(props, ...args)
this.state = { percentage: { width: '0%' } }
setInterval(() => this.setState({ percentage: { width: '50%' } }), 5000)
}
render() {
return <Start percentage={this.state.percentage} />
}
}
It's technically correct that a component updates when its props change; however, the only way to change its props is to re-render it! Props are read-only inside a component. Which is why I say it's misleading (or incomplete) to think about prop changes driving component re-rendering.
Upvotes: 4