Home > Web Front-end > JS Tutorial > State Management in React Native

State Management in React Native

尊渡假赌尊渡假赌尊渡假赌
Release: 2025-02-14 10:23:12
Original
659 people have browsed it

State Management in React Native

Core points

  • State in React Native refers to anything that changes over time, such as a counter in a counter application or a to-do list in a to-do application. It is managed using a variety of methods, including React's setState() method, the Context API, and recently introduced Hooks.
  • Context API provides a way to pass data in a component tree without manually passing props at each layer, thus avoiding the so-called "props drilling" problem. It allows data to be transferred directly between components.
  • React Hooks was introduced in React v16.8, simplifying the way state is used in React. They allow state use in function components, reduce the number of lines of code and make the code easier to read.
  • Sharing state across components can be achieved by elevating the state to the parent component. This practice, while not always straightforward, is common in React and helps prevent the parent component from becoming a large state object.

State management is one of the most difficult concepts to master in learning React Native, as there are many ways to implement it. There are countless state management libraries on the npm registry—such as Redux—and there are countless libraries built on the other state management libraries to simplify the original library itself—such as Redux Easy. A new state management library is introduced in React every week, but since the introduction of React, the basic concept of maintaining application state remains the same.

The most common way to set state in React Native is to use React's setState() method. We can also use the Context API to avoid props drilling and pass multi-layer state down without passing it to individual subcomponents in the tree.

Recently, Hooks appeared in React v16.8.0, a new mode that simplifies the use of state in React. React Native got it in v0.59.

In this tutorial, we will learn what state actually means, as well as the setState() method, the Context API, and React Hooks. This is the basis for setting state in React Native. All libraries are built based on the above basic concepts. So once you understand these concepts, it will be easy to understand the library or create your own state management library.

Want to learn React Native from scratch? This article is excerpted from our advanced library. Join SitePoint Premium now for a complete React Native book collection covering basics, projects, tips, and tools, for just $9 per month.

What is status?

Anything that changes over time is called a state. If we have a counter application, the state is the counter itself. If we have a to-do app, the to-do list changes over time, so this list will be status. Even the input element is a state in a sense, as it changes over time as the user types it in.

setState Introduction

Now that we know what state is, let's understand how React stores it.

Consider a simple counter application:

import React from 'react';
import { Text, Button } from 'react-native';

class Counter extends React.Component {
  state = {
    counter: 0,
  };

  render() {
    const { counter } = this.state;
    return (
      <>
        <Text>{counter}</Text>
        <Button title="Increment" onPress={() => this.setState({ counter: counter + 1 })} />
        <Button title="Decrement" onPress={() => this.setState({ counter: counter - 1 })} />
      </>
    );
  }
}
Copy after login
Copy after login
Copy after login

In this application, we store the state within an object in the constructor and assign it to this.state.

Remember that state can only be one object. You cannot store numbers directly. This is why we create a counter variable inside the object.

In the render method, we deconstruct the this.state attribute from counter and render it within <h1>. Note that at present it will only display static values ​​(0).

You can also write states outside the constructor as follows:

import React from 'react';
import { Text, Button } from 'react-native';

class Counter extends React.Component {
  state = { counter: 0 };

  render() {
    const { counter } = this.state;
    return (
      <>
        <Text>{counter}</Text>
        <Button title="Increment" onPress={() => this.setState({ counter: counter + 1 })} />
        <Button title="Decrement" onPress={() => this.setState({ counter: counter - 1 })} />
      </>
    );
  }
}
Copy after login
Copy after login

Now suppose we want the "" and "-" buttons to work. We have to write some code inside their respective onPress handlers:

import React from 'react';
import { Text, Button } from 'react-native';

class Counter extends React.Component {
  state = { counter: 0 };

  render() {
    const { counter } = this.state;
    return (
      <>
        <Text>{counter}</Text>
        <Button title="Increment" onPress={() => this.setState(prevState => ({ counter: prevState.counter + 1 }))} />
        <Button title="Decrement" onPress={() => this.setState(prevState => ({ counter: prevState.counter - 1 }))} />
      </>
    );
  }
}
Copy after login
Copy after login
Copy after login
Copy after login

Now, when we click the " " and "-" buttons, React re-renders the component. This is because the setState() method is used.

The

setState() method re-renders part of the changed tree. In this case, it re-renders <h1>.

So if we click " , it will increase the counter by 1. If we click "-", it will reduce the counter by 1.

Remember that you cannot change the status directly by changing this.state ; executing this.state = counter 1 will not work.

In addition, the state change is an asynchronous operation, which means that if you read this.setState immediately after calling this.state, it will not reflect the latest changes.

Here, we use the "function as callback" syntax to use setState() as shown below:

import React from 'react';
import { Text, Button } from 'react-native';

class Counter extends React.Component {
  state = { counter: 0 };

  render() {
    const { counter } = this.state;
    return (
      <>
        <Text>{counter}</Text>
        <Button title="Increment" onPress={() => this.setState(prevState => ({ counter: prevState.counter + 1 }))} />
        <Button title="Decrement" onPress={() => this.setState(prevState => ({ counter: prevState.counter - 1 }))} />
      </>
    );
  }
}
Copy after login
Copy after login
Copy after login
Copy after login

"Function as callback" syntax provides the latest state - in this case prevState - as a parameter to the setState() method.

In this way, we can get the latest changes to the state.

What are Hooks?

Hooks is a new feature in React v16.8. Earlier, you could only use state by creating class components. You cannot use state in the function component itself.

With the addition of Hooks, you can use state in the function component itself.

Let's convert the above Counter class component to Counter function component and use React Hooks:

import React from 'react';
import { Text, Button } from 'react-native';

const Counter = () => {
  const [counter, setCounter] = React.useState(0);
  return (
    <>
      <Text>{counter}</Text>
      <Button title="Increment" onPress={() => setCounter(counter + 1)} />
      <Button title="Decrement" onPress={() => setCounter(counter - 1)} />
    </>
  );
};
Copy after login
Copy after login

Note that we reduced the number of lines of code for a class component from 18 to only 12 lines. In addition, the code is easier to read.

Let's review the above code. First, we use React's built-in useState method. useState can be of any type—such as a number, string, array, boolean, object, or any type of data—unlike setState(), setState() can only have one object.

In our counter example, it takes a number and returns an array containing two values.

The first value in the

The first value in the array is the current state value. Therefore, counter is currently 0.

The second value in the

The second value in the array is a function that allows you to update the state value.

In our onPress, we can use setCounter to update counter directly.

Therefore, our incremental function becomes setCounter(counter 1) and our decremental function becomes setCounter(counter - 1).

React has many built-in Hooks such as useState, useEffect, useContext, useReducer, useCallback, useMemo, useRef, useImperativeHandle, useLayoutEffect, useDebugValue,

,

,

and

——You can find more information in the React Hooks documentation.

    In addition, we can build our own custom hooks.
  1. useStateTwo rules are required to be followed when building or using Hooks: useEffect
  2. Call Hooks at the top level only. Do not call Hooks within loops, conditions, or nested functions. Instead, always use Hooks at the top level of React functions. By following this rule, you can ensure that Hooks are called in the same order every time the component renders. This is why React is allowed to properly retain the Hooks state between multiple
  3. and
calls.

Call Hooks from React functions only. Do not call Hooks from regular JavaScript functions. Instead, you can call Hooks from the React function component or from custom Hooks.

By following this rule, you can ensure that all stateful logic in the component is clearly visible from its source code. Hooks are very easy to understand and are useful when adding state to function components.

Context API

Context provides a way to pass data in a component tree without manually passing props at each layer. theme AppIn a typical React Native application, data is passed from top to bottom via props. If there are multiple component levels in the React application and the last child component in the component tree wants to retrieve data from the topmost parent component, you must pass props down individually. Pic

Consider the following example. We want to pass the value of
import React from 'react';
import { Text, Button } from 'react-native';

class Counter extends React.Component {
  state = {
    counter: 0,
  };

  render() {
    const { counter } = this.state;
    return (
      <>
        <Text>{counter}</Text>
        <Button title="Increment" onPress={() => this.setState({ counter: counter + 1 })} />
        <Button title="Decrement" onPress={() => this.setState({ counter: counter - 1 })} />
      </>
    );
  }
}
Copy after login
Copy after login
Copy after login
from the

component to the theme component. Normally, if we don't use Context, we will pass it through each intermediate level, like so:

The value of

is passed from App -> Home -> Profile -> Pic. The above problem is called props drilling.

This is a simple example, but consider a real application with dozens of different levels.

<🎜>It becomes difficult to pass data through each child component just to use it in the last child component. So we have Context. <🎜> <🎜>Context allows us to pass data directly from App -> Pic. <🎜>

The following is how to use the Context API:

import React from 'react';
import { Text, Button } from 'react-native';

class Counter extends React.Component {
  state = {
    counter: 0,
  };

  render() {
    const { counter } = this.state;
    return (
      <>
        <Text>{counter}</Text>
        <Button title="Increment" onPress={() => this.setState({ counter: counter + 1 })} />
        <Button title="Decrement" onPress={() => this.setState({ counter: counter - 1 })} />
      </>
    );
  }
}
Copy after login
Copy after login
Copy after login

First, we use the React.createContext API to create ThemeContext. We set light to the default value.

Then, we use the theme to wrap the root element of the ThemeContext.Provider component with the App when we provide

as a prop.

ThemeContext.Consumer Finally, we use theme as the rendering prop to get the dark value is

.

ThemeContext.Consumer Rendering prop mode is good, but if we have multiple contexts, it can cause callback hell. To avoid callback hell, we can use Hooks instead of

.

ProfileThe only thing we need to change is the

component implementation details:
import React from 'react';
import { Text, Button } from 'react-native';

class Counter extends React.Component {
  state = { counter: 0 };

  render() {
    const { counter } = this.state;
    return (
      <>
        <Text>{counter}</Text>
        <Button title="Increment" onPress={() => this.setState({ counter: counter + 1 })} />
        <Button title="Decrement" onPress={() => this.setState({ counter: counter - 1 })} />
      </>
    );
  }
}
Copy after login
Copy after login

In this way, we don't have to worry about callback hell.

Shared state across components

So far, we have only managed state in the component itself. Now we will understand how to manage state between components.

Suppose we are creating a simple to-do list application as shown below:
import React from 'react';
import { Text, Button } from 'react-native';

class Counter extends React.Component {
  state = { counter: 0 };

  render() {
    const { counter } = this.state;
    return (
      <>
        <Text>{counter}</Text>
        <Button title="Increment" onPress={() => this.setState(prevState => ({ counter: prevState.counter + 1 }))} />
        <Button title="Decrement" onPress={() => this.setState(prevState => ({ counter: prevState.counter - 1 }))} />
      </>
    );
  }
}
Copy after login
Copy after login
Copy after login
Copy after login

AddTodo Now, if we want to add a to-do from the TodoList component, how will it be displayed in the todos prop of the

component? The answer is "Elevated State".

If two sibling components want to share the state, they must be promoted to the parent component. The complete example should look like this:
import React from 'react';
import { Text, Button } from 'react-native';

class Counter extends React.Component {
  state = { counter: 0 };

  render() {
    const { counter } = this.state;
    return (
      <>
        <Text>{counter}</Text>
        <Button title="Increment" onPress={() => this.setState(prevState => ({ counter: prevState.counter + 1 }))} />
        <Button title="Decrement" onPress={() => this.setState(prevState => ({ counter: prevState.counter - 1 }))} />
      </>
    );
  }
}
Copy after login
Copy after login
Copy after login
Copy after login

AppHere, we save the state in the useState component. We use React Hook todos to store

as an empty array.

addTodo Then we pass the AddTodo method to the todos component and pass the TodoList array to the

component.

The AddTodoaddTodo component receives the

method as a prop. This method should be called after pressing the button.

TextInputWe also have a useState element, which also uses React Hook TextInput to track the change value of

.

AppAfter pressing the button, we will call the addTodo method passed from the parent todos. This ensures that the to-do items are added to the TextInput list. We will clear the

box later.

TodoListtodos The component receives

and presents it to do list.

You can also try to delete a to-do item to practice improving yourself. Here is the solution:
import React from 'react';
import { Text, Button } from 'react-native';

const Counter = () => {
  const [counter, setCounter] = React.useState(0);
  return (
    <>
      <Text>{counter}</Text>
      <Button title="Increment" onPress={() => setCounter(counter + 1)} />
      <Button title="Decrement" onPress={() => setCounter(counter - 1)} />
    </>
  );
};
Copy after login
Copy after login

This is the most common practice in React. The improvement is not as simple as it seems. This is a simple example, but in a real application we don't know which state needs to be promoted to its parent for use in sibling components. Therefore, first, the state is kept in the component itself, and only when a situation occurs when it is necessary to share the state between components, the state is promoted to the parent.

In this way, you do not make the parent component a large state object.

Conclusion

All in all, we understand what state is and how to set state values ​​using the setState() API provided by React. We also learn about React Hooks, which makes it easy to add state to function components without converting them into class components.

We learned the new Context API and its Hooks version useContext, which helped us avoid rendering prop callback hell.

Finally, we learned how to improve state to share state among sibling components.

React becomes very simple once you understand these core concepts. Remember to keep the state local to the component as much as possible. Use the Context API only if props drilling becomes a problem. Promote state only if needed.

Lastly, once your application becomes complex and difficult to debug state changes, check out state management libraries like Redux and MobX.

FAQs about React Native State Management

What is state management in React Native? State management in React Native refers to the management and processing of state (data and UI logic) in a React Native application. It involves efficiently updating and synchronizing states in different components of an application.

Why is state management important in React Native development? State management is critical to React Native because it maintains and updates the application's dynamic data and user interface. It ensures that changes in part of the application are accurately reflected in other parts, providing a seamless and responsive user experience.

What are the different ways to manage state in React Native? React Native provides a variety of state management methods, including local component state, React Hooks (useState), Redux, MobX, and context APIs. The choice depends on the complexity and specific requirements of the application.

When should I use local component state with global state management solutions like Redux or MobX? For simple, local state management within components, use local component state. For complex applications that share state among multiple components, consider using global state management solutions such as Redux or MobX to maintain centralized and easily accessible state.

How does the Context API facilitate state management in React Native? The Context API is a feature in React that allows components to share state without explicitly passing props through component trees. It is useful for managing global state without the need for additional libraries like Redux.

This revised output maintains the original image locations and formats, rephrases the text for originality while preserving the core meaning, and addresses the prompt's requirements.

The above is the detailed content of State Management in React Native. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template