Hi Vicky,
I am also stuck in the infamous jammming project right now, so believe me I feel your pain
.
But with regards to props, I think this link helped me a lot, together with the next section that talks about state and how you combine both in action. That and something that also helped me a lot was doing this final exercise/mini-project in their docs. I think React has done an amazing job with their docs to be honest. That could be part of the reason for their success.
What helps me a little with props is thinking of this game where there’s a group of people and one of them has to whisper a secret message to the ear of the one at their side, and this one in turn whispers the secret to the ear of the next one, and so on. The final person of the chain will receive this message, but if you’re not part of the chain, you don’t know what the message is, right? Well, this is what happens with props:
You make a component A:
class ComponentA extends ... {
}
Then, that component will have, for example, a method (although this also applies to the state) that for example, logs something to the console.
So…
class ComponentA extends ... {
// In the constructor you bind
// the method, etc, etc
constructor ...
logMyValue(myValue) {
console.log(myValue);
}
}
Now, let’s suppose that ComponentA wants to print a value you type into another component. How will ComponentA know what value to print? And when will it know to print it?
That is why, when you create the component that has the input where you typed you pass the prop of the logMyValue “ability” if you want, and the child component will contribute the value. See:
class ComponentA extends ... {
// In the constructor you bind
// the method, etc, etc
constructor(props) ...
logMyValue(myValue) {
console.log(myValue);
}
render() {
return (
// Here componentA whispers the method to CompB
<ComponentB logValue={this.logMyValue} />
);
}
}
class ComponentB extends ... {
handleChange(event) {
// Here you assign the value you typed to a variable...
const value = event.target.value;
// ...that then you use as arg for the logValue method of CompA
this.props.logValue(value);
// But wait, how did this method get here if it's in CompA?
// It was whispered by CompA. Check above, inside CompA.
}
render() {
return (
// Here, you tell the input in CompB: whenever you change,
// handle the event with this method (this.handleChange)
<input type="text" onChange={handleChange} />
);
}
}
And then the whisper chain can even come back with an answer, too!
For example, if you want to change the state of CompA for some reason, you could add a this.setState() call inside this method declaration (in CompA) and when you call it in CompB, the state of the former will be updated, right?
Like this:
class ComponentA extends ... {
// In the constructor you bind
// the method, etc, etc
constructor(props) {
super(props);
this.logMyValue = this.logMyValue.bind(this);
this.state = {
value: 'Nothing now! :('
}
}
logMyValue(myValue) {
this.setState({
value: myValue
})
console.log(myValue);
}
render() {
return (
<ComponentB logValue={this.logMyValue} />
);
}
}
class ComponentB extends ... {
handleChange(event) {
const value = event.target.value;
this.props.logValue(value);
}
render() {
return (
<input type="text" onChange={handleChange} />
);
}
}
That above would now update the state of CompA with the value you passed from CompB. There was effectively another whispering chain back, in a way.
Jokes aside, I hope the example will help a little to understand this, which I know, it’s a little bit tricky.