Beginner : Understanding data, Props vs State

We saw in the previous post how in React we could create a simple component, and we also saw how to pass an arbitrary data to be displayed through an attribute.

We will see this time how to manage data in a more complete way, trying to understand how React manages immutable and mutable data within components.

Let’s start with the example of the previous post.

// How to define
function Label(props: {text: string}) {
  return <span>{props.text}</span>;
}
Enter fullscreen mode

Exit fullscreen mode

{/* How to use */}
<div>
  <Label text="Hello Kitty"/>
</div>
Enter fullscreen mode

Exit fullscreen mode

Props

When we use a component, and we want to pass a data to it, we send this information through an attribute. And for the component, it is a field within an object that we named Props (For properties).

From the component’s perspective, a property is a value that does not belong to it, it comes from its parent, which can be another component, or it can be called from the root code fragment.

At this point, let’s consider that this just comes from the outside.

These data are considered immutable, i.e. they can be seen as read-only. We can / must NEVER modify them.

The validity of the data state is the parent’s responsibility. A component that uses only such data will be predictable. It will be called a pure function, in the meaning that the result will always be the same according to the value of the parameters given to it.

The data can be content display information, as well as technical data about the component’s internal status.

In our example, we had a text, so raw display data. Let’s add for example a style data.

// How to define
function Label(props: {text: string, color: string}) {
  return <span style={ {color: props.color} }>{props.text}</span>;
}
Enter fullscreen mode

Exit fullscreen mode

{/* How to use */}
<div>
  <Label text="Hello Kitty" color="red"/>
</div>
Enter fullscreen mode

Exit fullscreen mode

So we added a field in the Props object to manage the color, and connected this field in our component. We can manage a bit of everything this way.

How, if we delegate the state of the data to the parent, can we make the component interactive?

As we are in (Java/Type)script, and it is a functional language, passing a function as a parameter is something common, so it is just as simple to expect to pass a function as an attribute.

// How to define
function Label(props: {text: string, onClick: () => void}) {
  return <span onClick={props.onClick}>{props.text}</span>;
}
Enter fullscreen mode

Exit fullscreen mode

{/* How to use */}
<div>
  <Label text="Hello Kitty" onClick={() => console.log("Clicked !")}/>
</div>
Enter fullscreen mode

Exit fullscreen mode

In this way the parent can be notified, make changes and provide new data to the component. Each time the data is changed, the component will be redrawn automatically.

State

To keep it simple, the State will define data that is local to the component, and which will be unknown outside the component, and that will be mutable.

Let’s imagine that our component displays or hides its content on click, it will be its responsibility to hide or not the content, and therefore it will have to manage its state locally.

To do this, we will use the useSate method to define a state. This method is called a Hook but it is not the topic of this post.

// How to define
type Props = { title: string, content: string };

function Label(props: Props) {
  // Define the state, expanded is the value
  // setExpanded a function to mutate the value
  const [expanded, setExpanded] = useState(false);

  return <div>
    <h6>{props.title}</h6>
    <div onClick={() => setExpanded(!expanded)}>{props.content}</div>
 </div>
}
Enter fullscreen mode

Exit fullscreen mode

The useState function will have as parameter, the initial value. expanded will be the current value in the scope, and to mutate it, we will use the setExpanded function. It is quite simple.

Now, each time a state is mutated, React will re render this component automatically. You can define as many states as you need, you are not forced to have one to store all values.

Be aware that when you mutate a state value, it will be fully replaced. So it is better to split the state logic in several state values depending on the complexity of the component.

For example, we can, at a minimum, separate the storage of the internal states from those of the displayed data.

That’s all for this post. In the next one, we’ll see how to adopt the mindset needed for component design, and when to choose the use of properties, or states.

Enjoy.

Author: admin