Hey guys, I'm a Rails ''entry'' developer(unemployed) and I am now in my part time trying to learn React, I saw in a tutorial where they ''lift state up'' so the State only lives in the parent component and it passes down to its children component via props, now, how common is that? Is it better that way or should I leave each components with its own state.
I think it's much messy but idk, I'm a begginer!
For further actions, you may consider blocking this person and/or reporting abuse
Top comments (3)
Passing props down and lifting state is basically the first tool you have for "state management". Is it common? I believe it should. Can it get messy? Yes, absolutely. That's why React has added features like the "context api" or the new hooks. And also there are 3rd party tools like
redux
that can help you manage the state.But you can do a lot using just props and component composition. Here is a video that show how to use component composition.
Say you have a function. A function, in this context, is a little reusable piece of functionality that takes some instructions (in the form of values), does {something} with them, and returns a value. When you run it, passing it the values it requires, it runs whatever procedure is defined and returns a value.
add
takes two numbers and returns the sum of them.add(1,2)
, that's 3.That function doesn't store anything, it just does the addition. And if you give it the same arguments it always returns the same thing. A React app is normally made up of lots of functions like this. That's great, as it makes things relatively simple.
This has a slightly weird syntax, but like
add
, it's just a function that takes a value and returns a value. The way you call it is a bit different as well --<Greeting name="Dan" />
. And in the browser, there's this:<p>Hello, Dan!</>
.But GUI applications normally need know what happened previously. They need to store the results of user actions somewhere -- they need to handle state.
To go back to
add
, say you want to add up a collection of numbers. You need the program to remember what the last result was. It needs state. That state can't be stored in theadd
function, it needs to be stored outside of it.Functions are slightly special in JavaScript. It's not just the instructions of what a function does that are stored in the computer's memory. It is that plus any variables that are defined inside it.
So with that in mind, what you can do is wrap
add
in another function. The value of the state (the running total) is defined in that function, and that function can use that and runadd
as many times as needed.sum([1,2,3,4,5])
. That would be 15!Note that this way of looping over a collection and running a function on the previous result and the current item happens to already be built into JS, so can just write it as:
So to go back to React, say you have a function that returns an
input
.And you want to reuse that wherever you need some user input. Without being able to store the result of the input action somewhere those functions really aren't much use. The
Input
function will allow a user to enter some input, but it's unlikely to be useful in the context of an application.For example, if you're creating a form, you might have a few inputs, and you need to collect the values from them in one place. So you lift the state up from the inputs to the form function. Very simplified example:
And you can keep doing this, moving the state upwards through the components. As sibling commenters have noted, this can get messy and difficult to keep track of as you add more and more components. So:
n.b. this is a simplification of how and where local state is retained w/r/t state hooks. And a component function (+ JSX) goes through a fair few stages before actually returning a value, it doesn't do it directly. But I would say the principles are exactly the same.
React, like other newer web frameworks work with "Web Components" -- the idea of encapsulating common functional components of a web app into discrete blocks to be reused.
State management and encapsulation are two different programming concepts that sometimes work against each other.
Let's look at a simple example:
I want to create a
PasswordField()
component, which is an input field that contains the following functionality:I also want to do some form validation on this field -- specifically we want to know if the entered text matches a specific password format I've specified.
Now, when I try to use my password field, I decide to put it in a form. I only want this form to be submittable if all of the fields in the form validate successfully.
Here's where our problems start -- our validation is encapsulated in the
PasswordField()
component, which means my form won't know if it validates. This is obviously a problem."Lifting state up" in this context, would encourage me to remove my validating state (whether or not my field is valid) by making the form responsible for this state, instead of my component.
This is what we're talking about -- moving state from a child component into the parents that manage it. It makes sense in how we actually use the state, but stands opposed sometimes to the idea of encapsulation. This is one of the reasons why we have so many other state management tools we can work with.