React state and props work as a pair: state holds data a component owns, and props pass data down to child components. Changing state re-runs the function component, which re-renders the JSX and sends fresh props to every child that receives them.
How do React state and props work together?
React state and props are two channels for data in one component tree: state is owned by a component and changed through its setter function, while props are read-only values passed from a parent. This article's focus is the Hooks API, the default way to write components since React 16.8 shipped in February 2019, and the approach used in the source video on Gustavo Dev Doido's channel published in September 2019 React Hooks documentation.
Before Hooks, the same lesson would have used class components and this.setState. The Hook version calls useState at the top of a function, which returns the current value and a setter. React's rules of hooks require that call to run unconditionally on every render, in the same order, so it stays readable to the renderer.
Two facts about state drive everything else in this guide. Setting state does not change the variable you already hold; it schedules a new render with a new value. And because the new value arrives on the next render, code that reads state immediately after calling the setter still sees the old value.
Using useState and useEffect to update a name
The first step is holding the form input's value in state and letting React re-render the input on each keystroke. The input gets value={name} and an onChange handler that calls the setter with event.target.value. The video shows exactly this wiring for a name field billed in the transcript as part of a demo.
The effect hook was part of the same 2019 lesson, used to run something whenever a value changes. Most input handling does not need an effect at all: the setter inside onChange already triggers the render. An effect is for syncing with something outside React, such as a document title or a network request, and its dependency array decides when it re-runs, as described in the useEffect reference.
One practical note from the transcript is worth keeping: returning a fragment, <></>, lets you render several siblings from one component without adding an extra element to the DOM. React's documentation lists that use case among the main reasons to use fragments.
Why does React state have to stay immutable?
React compares the previous state value with the next one, so a change made in place can be missed when you use state that is worth memoizing. When state holds an array, replace the array with a new one rather than pushing into the old one. The pattern below adds a name and removes a name with two new arrays.
The two setter calls follow the same shape. Each builds a fresh array with the spread operator or filter, then passes it to the setter. React's updating arrays in state guide gives the same two recipes and explains that push, splice and index assignment should be avoided on state arrays.
If a new value depends on the previous one, use the updater form, setNames(previous => previous.filter(...)). The updater guarantees the freshest value in a single update, which matters when several updates are batched into one render.
Removal deserves a plain sentence of its own: you do not delete an item from state, you assign a new array that omits it. The video makes this point against a common expectation that the original list is being edited.
Adding and removing list items: a worked sequence
A complete add-and-remove loop needs a controlled input, a name held in state, an array of names held in state, and a submit handler that copies the array. The steps below keep the state immutable at every point and need no library.
- Create the input state with
useState('')and the list state withuseState<string[]>([]). - Bind the input with
valueandonChange, and call the setter withevent.target.value. - In the form's submit handler, call
preventDefault, build a new array with[...names, newName], pass it to the list setter, and clear the input. - Give each rendered entry a stable key, such as the name plus an index, or a generated id.
- For removal, call the list setter with
names.filter(name => name !== target).
React's rendering lists guide recommends a stable identity for keys, warning that array indexes produce confusing behaviour when items are reordered or removed. A name string works when names are unique; an id generated at creation is safer for a real list.
The video also builds a child component for one list row, passing the name as a prop and the delete handler as a second prop. That callback is how a child asks its parent to change state: the parent owns the array and the function, and the child only calls the function with the name it was given.
How do you pass functions and defaults through props?
Props carry both data and behaviour: a parent hands a child a value to display and a function to call, and the child never touches the parent's state directly. This keeps one owner per piece of state, which is the pattern the video reaches when it breaks a list row into its own Pessoa component.
Default props cover the case of an optional field. In the Hooks era, a default parameter on the destructured props object does the same job with less ceremony. Class components used a static defaultProps property, and React removed that support for function components in version 19, which shipped on 5 December 2024.
Type checking is the other half of the same topic. The video installs prop-types and marks a prop as required with .isRequired, so a missing value produces a console warning during development. TypeScript is the other option, and it checks props at compile time instead of at runtime. If you want a guided path through the TypeScript side of this stack, Crazystack TypeScript is the programme the channel behind this walkthrough references.
Default values and required values do different jobs. A default keeps an optional prop from being undefined; isRequired in prop-types flags a prop the caller must supply, though it never prevents the component from rendering.
React state and props at a glance
State and props differ in who may change them, where the value lives, and what a change triggers. The table below compares the two, plus a third mechanism worth naming beside them, so the choice is visible in one place.
| Aspect | State | Props | Context |
|---|---|---|---|
| Who changes it | The owning component, via its setter | The parent, by re-rendering | Any consumer, via its provider's setter |
| Direction of flow | Stays in the owner, flows down as props | Parent to child only | Provider to any descendant |
| What a change does | Re-renders the owner and its children | Comes with the parent's render | Re-renders consumers |
| Typical use | Form input, list contents, toggles | Display values, callbacks | Theme, auth, locale |
| Main pitfall | Mutating in place | Passing unstable inline callbacks | Overusing it for local data |
The main caveat is that the table describes defaults, not laws. Passing, say, a filtered list down as props keeps the child simple, while putting every value into context makes components harder to reuse elsewhere. React's passing props to a component page covers the parent-to-child pattern in detail.