The original link: learnreact. Design / 2018/01/15 /…

Why you like it: Vivid and easy to understand

Special thanks to Linton Ye, the original author

Blog series: Explain the React term in colloquial terms and doodles

  • The illustration the React
  • The illustration React Native
  • Component, Props, and State
  • Understanding Props and State (this article)
  • React Native vs. Cordova, PhoneGap, Ionic, etc.

In the last article, we introduced components, props, and state.

The difference between props and state is pretty clear, and it seems pretty simple to determine when to use them. For example, the color of the roof is naturally a prop, because color is an inherent property of the roof. On the other hand, the open and open state of the door is clearly state, because the door can be opened or closed after it has been created. In this article, however, we challenge that way of thinking!

No kidding? ! ? Yes, what you’re looking at can be either a prop or a state. There are no absolute limits. I’ll introduce a more useful, real-world way of thinking about Prop and state.

Learning goals

After you’ve read this article, I wish you’d come back here and be able to easily answer the following questions:

  • What are the main uses of props and state?
  • What does “state promotion” mean? In what scenarios do you need to promote state?

New members

Have you noticed any new recruits around the house? Try clicking on the door!

Check out the React Cottage with Cats Demo in CodePen by focuser (@focuser).

This is a lethargic cat. She sleeps when the door is closed and only gets up when it is opened again. If the door was closed, she would immediately fall asleep again.

To realize the cat

Now LET me ask you, what if you implement cat behavior? Try it first!

Start with the following “code” and take the time to read through it first. (Again, this isn’t real JavaScript code, it’s just a simplified form to help you understand the concept without being distracted by the details in JS.)

House:
  <div>
    <Roof />
    <Wall />
    <Window />
    <door />
    <Cat />
  </div>Door: State: status <! --"open""closed" -->
  <div>{state.status} door</div>When clicking on a door if door.state.status is"open"Change door.state.status to"closed"Otherwise, change door.state.status to"open"
Copy the code

Added the Cat tag to the House component. So what about the Cat component? So let’s define it.

The cat either sleeps or wakes up. It seems to be similar to the open and closed state of a door. Perhaps we could also use state to represent the state of the cat:

Cat: State: status <! --"sleeping""awake" -->
  <div>{state.status} cat</div>
Copy the code

With the Cat component defined, all that remains to be implemented is to synchronize the state of the Cat and the gate. When the door is in the “open” state, we want the cat to be “awake” and otherwise “sleeping”.

Is it that simple? Let’s see…

First try

Now that we have the code to switch the state of the gate based on the current state, let’s switch the state of the cat here:

Door: State: status <! --"open""closed" -->
  <div>{state.status} door</div>If state.status is when the door is clicked"open"Change state.status to"closed"Change cat.state.status to"sleeping"<! -- False --> Otherwise change state.status to"open"Change cat.state.status to"awake"<! -- Wrong -->Copy the code

Unfortunately, it doesn’t work! Remember that a component’s state is private data? It is accessible only from within the component. No other component, parent or sibling, can access the state of this component.

Unfortunately, our attempts to modify the state of the cat in the Door component failed. (Converting to real JavaScript code is no exception.)

Second try

How about changing the state of the Cat in the Cat component? It should work this time, right?

Cat: State: status <! --"sleeping""awake" -->
  <div>{state.status} cat</div>When clicking on the door <! -- Black man face?? What's the click method? --> If door.state.status is"open"<! -- Incorrect --> change cat.state.status to"sleeping"Otherwise, change cat.state.status to"awake"
Copy the code

There is no question that it is ok to modify the state of a Cat within the Cat component. But we need to read the state of the gate to determine what the state of the cat is. The state of the Door is the state of the Door component, so it cannot be accessed in the Cat component!

The solution

Well! That’s lame. To keep the door and cat in sync, we have to be able to access both at the same time somewhere. But it looks like the data is hidden by design. How to solve this problem?

The solution is that we need to be flexible in understanding the use of state and props.

State of the upgrade gate

House components:

House:
  <div>.<door />
    <Cat />
  </div>
Copy the code

Door and Cat are placed side by side. Maybe this is where it’s easy to synchronize them?

However, we are now inside the House component. As in previous attempts, there is no way to read Door’s state or change Cat’s state.

But what if we use props instead of state?

House:
  <div>
    ...
    <Door status="open" />
    <Cat status="awake" />
  </div>
Copy the code

When the door closes:

House:
  <div>
    ...
    <Door status="closed" />
    <Cat status="sleeping" />
  </div>
Copy the code

Of course, the state of the gate will not be fixed, it will change over time. We use doorStatus to describe the state of the door.

House: <div> ... <Door status={doorStatus} /> <Cat status={awake' if doorStatus is 'open' otherwise 'sleeping'} /> </div>Copy the code

That solves the synchronization problem. By the way, what is doorStatus, which is changing? What can be changed in a component? That’s right, state.

House: State: doorStatus <! --'open''closed'--> <div> ... <Door status={state.doorStatus} /> <Cat status={if state.doorStatus is 'open', the value is 'awake', otherwise it is 'sleeping'} /> </div>Copy the code

That’s great! The House component is now well defined and the states of the door and cat are in perfect sync.

We also need to modify the Door and Cat components to use props instead of state:

Door:
  <div>{props.status} door</div>
Cat:
  <div>{props.status} cat</div> 
Copy the code

As you can see, since we want to use the state from the parent component, in this case, to set the state of the cat, the state of the door is actually from House, we can represent the same data as the parent component’s state, and pass that data to the child component as props. In general, this is called state promotion. We move state to a higher level of the component.

Change the state of the house

The state of the door and cat is now connected via the state of the house. If we want to open the door or wake up the cat, we need to change the state of the House component.

Where is the only place to update the state of the House? It’s in the House component, right?

However, we want to trigger this change in the Door. That is, we want an effect that opens only when the door is clicked, not when the whole house or window is clicked, etc.

So the Door component needs some changes:

Door:
  <div>{props.status} door</div>Do something to modify when the door is clicked`House`The state ofCopy the code

But wait, didn’t we say we couldn’t change the state of House in the Door component?

That’s right. We can’t directly modify the state of House. But that doesn’t mean it can’t be modified indirectly. See below…

Inside the House component, let’s write code to actually change its state:

House: State: doorStatus <! --'open''closed'--> toggleDoorStatus: If state.doorStatus is'open'Change state.doorStatus to'closed'Otherwise, change state.doorStatus to'open'.Copy the code

At this point, we haven’t specified when to run this code. We just gave it a name (toggleDoorStatus) so that we could find it running later by the name.

ToggleDoorStatus is then passed to the Door component as a prop:

House:
  ...
  <div>
    ...
    <Door ... onClickAction={toggleDoorStatus} />
    ...
  </div>
Copy the code

In the Door component, we simply perform this click:

Door:
  <div>{props.status} door</div>Executes props. OnClickAction <! -- The actual run is called"toggleDoorStatus"The code -- -- >Copy the code

It’s like passing the TV remote control to someone else. Someone pressed the remote button inside the Door component. The TV in the House component changes channels or turns up the volume.

What happens depends on what remote is passed to Door. It might control the TV in the room, the air conditioner or the hi-fi sound system. Inside the Door component, all someone needs to do is press a button on the remote control.

That’s all we need! Here is the full “code” :

House: State: doorStatus <! --'open' or 'closed'--> toggleDoorStatus: If state.doorStatus is'open'Change state.doorStatus to'closed'Otherwise, change state.doorStatus to'open'
  <div>
    ...
    <Door status={state.doorStatus} onClickAction={toggleDoorStatus} />
    <Cat status={if state.doorStatusAs'open'a value of'awake'Otherwise'sleeping'} / >
  </div>
Door:
  <div>{props.status} door</div>Execute props. OnClickAction Cat when the door is clicked:<div>{props.status} cat</div>  
Copy the code

Look again at Props and State

Now let’s go over a few questions. What’s the difference between props and state? When should YOU use State? When should I use props?

When to use state? When to use props?

If you remember, I said props is an intrinsic property of the component that doesn’t change, while state is a property that was created after the component was created and can be changed. It is helpful when initially learning these two concepts.

However, the example we just created makes this point confusing. Whether the door was open, or the cat was asleep, which would certainly be state, we use props for them. Why is that?

As it turns out, there is a lot of flexibility when it comes to choosing between state and props. Depending on how you look at it, you can model components in different ways. For example, when the door is open, you can say it’s the state of the door, you can say it’s the state of the house.

A more useful way of thinking about it

Confused? Here’s a more useful way to think about it:

  • State: If the UI needs to be changed it means there must be State somewhere
  • Props: used to pass data and control

When the application is running, if the UI needs to change, it must be state. When a door opens or closes when clicked, it must be a state somewhere.

However, state is not necessarily the state of the update component. It may be in an upstream component. It all depends on where and how we need to use that information. For example, we decided to elevate the state of the Door from the Door component to the House component because we need to use it in the House component.

Props, on the other hand, is just something you use to pass data down. Just as we passed the state of the Door from the House component down to the Door component.

Props can also be used to pass control down. For example, we pass the event handling method from House to Door.

Does the props change in this example?

No, props never change their value. I know what you mean. Doors open and close, cats sleep and wake up. Since we now refer to them as props, it’s easy to think that props behave like state, and that their value has changed, right?

This is just an illusion, and I find it quite similar to the animation of a turning book.

Every time the state of the house changes, the old cat disappears and a new cat is created. But it happens so fast that we have the residual vision of just one cat sleeping and waking up.

The sketches on any page in the book do not move. Similarly, each cat remains awake/asleep throughout its (brief) life.

conclusion

Well, we’ve learned props and state again with a more complex example. In this example, when the door is clicked, the door needs to toggle its on-off state, and we also need to synchronize the state of the door and the cat,

Since state is private, we need to promote the state of the Door from the Door component to the House component. We can then use this data in the House component to set the state of the door and cat. We pass this data to Door and Cat as props so that they will display the correct picture based on the state of the Door.

Another requirement is to trigger a change in state when a door is clicked. Because the state of the Door is now House state, it is private data and can only be changed indirectly in the Door component. We wrote the code in the House component that actually modifies state, and then passed it to Door as props. It’s similar to passing the TV remote control to someone else.

The examples in this article may confuse you a little. Here’s a more practical way to think about prop and state:

  • State: If the UI needs to be changed it means there must be State somewhere
  • Props: used to pass data and control

How are you feeling so far? If you have any questions or comments, please leave me a message!