Popular Searches
Popular Course Categories
Popular Courses

State Management Using the useState Hook

State Management Using the useState Hook

React Fundamentals for React Native

State Management Using the useState Hook in React Native

Course: React Native Training

Topic: State Management Using the useState Hook

Course Link: React Native Training Course

Demo Registration: Register for a Course Demo

JustAcademy Website: Visit JustAcademy


1. Introduction to State Management

State management is the process of storing, updating, and organizing data that changes while an application is running. In React Native, state helps an application respond to user interactions and display updated information without manually modifying the interface.

For example, a mobile application may need to remember a counter value, the text entered in a form, whether a password is visible, which tab is selected, or whether a user has marked a task as completed.

React provides the useState Hook to manage local state inside functional components. When state is updated using its setter function, React schedules a render so that the interface can reflect the new value.

1.1 What Is State?

State is data that a component needs to remember between renders. Unlike an ordinary local variable, state is maintained by React and can trigger a new render when updated.

Examples of state include:

  • A counter value displayed on the screen.
  • A user's name entered into a form.
  • The on/off status of a settings switch.
  • The currently selected product category.
  • A list of tasks in a to-do application.
  • The loading status of a network request.
  • Whether a modal or dropdown is visible.

1.2 Why Is State Management Important?

  • Interactive interfaces: State allows screens to respond to user actions.
  • Dynamic content: The UI can display updated information when data changes.
  • Form handling: State can store values entered by users.
  • Conditional rendering: Components can display different content depending on state.
  • Application behavior: State can track selected items, preferences, and progress.
  • Better user experience: Users receive immediate visual feedback when they interact with controls.

2. Introduction to the useState Hook

useState is a built-in React Hook that lets functional components declare and update state. It is imported from the React package and called at the top level of a function component or another custom Hook.

The Hook returns an array containing two items: the current state value and a setter function for updating that value.

2.1 Basic Syntax

import { useState } from 'react';

const [state, setState] = useState(initialValue);

In this syntax:

  • useState is the React Hook used to declare state.
  • initialValue specifies the initial state value.
  • state represents the current state value for the render.
  • setState requests an update to the state.

2.2 Example of useState in React Native

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

function CounterApp() {
  const [count, setCount] = useState(0);

  return (
    <View>
      <Text>Count: {count}</Text>
      <Button
        title="Increase"
        onPress={() => setCount(count + 1)}
      />
    </View>
  );
}

export default CounterApp;

Initially, the counter displays zero. When the user presses the Increase button, setCount requests an update to the state. React renders the component again, and the new counter value appears on the screen.

3. Understanding the Two Values Returned by useState

The useState Hook returns two values in an array. JavaScript array destructuring allows these values to be assigned meaningful variable names.

3.1 State Variable

The state variable contains the current value that React provides for the current render.

const [username, setUsername] = useState('Guest');

Here, username initially contains the string Guest.

3.2 State Setter Function

The setter function requests a new state value. React then schedules a render so the component can use the updated state.

setUsername('Asha');

After React processes the update, the next render receives Asha as the current username.

3.3 Naming Conventions

A common convention is to name the state variable and setter using a matching pair:

State Variable Setter Function Purpose
count setCount Stores a counter value.
username setUsername Stores a username.
isVisible setIsVisible Tracks visibility.
isLoading setIsLoading Tracks a loading state.
tasks setTasks Stores a task collection.
selectedTab setSelectedTab Tracks the selected tab.

4. Choosing an Initial State Value

The initial value passed to useState should match the type and purpose of the data being stored. React uses it to initialize the state when the component is first rendered.

4.1 Number State

const [count, setCount] = useState(0);

Use a number for counters, quantities, scores, or numeric selections.

4.2 String State

const [name, setName] = useState('');

Use a string for text input, search queries, names, or messages.

4.3 Boolean State

const [isEnabled, setIsEnabled] = useState(false);

Use a Boolean for on/off values, visibility flags, and simple conditions.

4.4 Array State

const [items, setItems] = useState([]);

Use an array for collections such as tasks, products, messages, or selected filters.

4.5 Object State

const [user, setUser] = useState({
  name: '',
  email: '',
  city: '',
});

Use an object when several related properties belong together, such as user details or form fields.

4.6 Initial State Reference Table

Data Type Example Initial Value Typical Use
Number 0 Counter or quantity.
String '' Text input or search field.
Boolean false Toggle or visibility status.
Array [] List of records.
Object {} Grouped data.
Nullable value null A value that is not available yet.

5. Updating State Correctly

State should be updated through the setter function returned by useState. Do not directly assign a new value to the state variable.

5.1 Incorrect State Update

const [count, setCount] = useState(0);

count = count + 1;

This is incorrect because the state variable is not a normal mutable variable, and direct assignment does not tell React to update the component.

5.2 Correct State Update

const [count, setCount] = useState(0);

setCount(count + 1);

The setter requests the new value. React can then render the component with the updated count.

5.3 State Updates Do Not Immediately Change the Current Render

A setter does not change the state variable in the already-running function. The updated value is available in a subsequent render after React processes the update.

function Example() {
  const [count, setCount] = useState(0);

  function handlePress() {
    setCount(count + 1);
    console.log(count);
  }

  return (
    <Button title="Increase" onPress={handlePress} />
  );
}

In this example, the console.log(count) statement reads the value from the current render, not the value requested by the setter. This behavior is expected in React.

6. Functional State Updates

When a new state value depends on the previous value, use the functional updater form. This is especially useful when several updates are queued during the same event.

6.1 Syntax

setCount(previousCount => previousCount + 1);

The updater function receives the previous state and returns the next state.

6.2 Example: Increment and Decrement Counter

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

function Counter() {
  const [count, setCount] = useState(0);

  function increase() {
    setCount(previousCount => previousCount + 1);
  }

  function decrease() {
    setCount(previousCount => previousCount - 1);
  }

  function reset() {
    setCount(0);
  }

  return (
    <View>
      <Text>Current Count: {count}</Text>
      <Button title="Increase" onPress={increase} />
      <Button title="Decrease" onPress={decrease} />
      <Button title="Reset" onPress={reset} />
    </View>
  );
}

export default Counter;

6.3 Why Use a Functional Updater?

  • It calculates the next state from the previous state.
  • It is useful when updates depend on earlier values.
  • It helps avoid stale-value problems in queued updates.
  • It supports predictable state transitions.

6.4 Multiple Updates in One Event

function increaseThreeTimes() {
  setCount(value => value + 1);
  setCount(value => value + 1);
  setCount(value => value + 1);
}

Each updater receives the result of the previous queued updater, so the count increases by three when React processes these updates.

7. Managing Boolean State

Boolean state is useful for values that can be either true or false. Common examples include opening a modal, showing a password, expanding a section, or enabling a setting.

7.1 Example: Show and Hide Password

import React, { useState } from 'react';
import { View, Text, TextInput, Pressable, StyleSheet } from 'react-native';

function PasswordField() {
  const [password, setPassword] = useState('');
  const [isPasswordVisible, setIsPasswordVisible] = useState(false);

  return (
    <View style={styles.container}>
      <Text>Password</Text>
      <TextInput
        value={password}
        onChangeText={setPassword}
        secureTextEntry={!isPasswordVisible}
        placeholder="Enter password"
        style={styles.input}
      />
      <Pressable
        onPress={() => setIsPasswordVisible(value => !value)}
      >
        <Text>
          {isPasswordVisible ? 'Hide Password' : 'Show Password'}
        </Text>
      </Pressable>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    padding: 16,
  },
  input: {
    borderWidth: 1,
    borderColor: '#999999',
    padding: 10,
    marginVertical: 10,
    borderRadius: 6,
  },
});

export default PasswordField;

7.2 Explanation

  • password stores the entered text.
  • isPasswordVisible controls whether the password is masked.
  • onChangeText updates the password state as the user types.
  • secureTextEntry is set to the opposite of the visibility state.
  • The pressable control toggles visibility.

8. Managing String State

String state is frequently used for search inputs, names, email addresses, comments, and form messages. In React Native, TextInput can be controlled by providing a value from state and updating it with onChangeText.

8.1 Example: Live Name Input

import React, { useState } from 'react';
import { View, Text, TextInput } from 'react-native';

function NameInput() {
  const [name, setName] = useState('');

  return (
    <View>
      <Text>Enter Your Name</Text>
      <TextInput
        value={name}
        onChangeText={setName}
        placeholder="Type your name"
      />
      <Text>Hello, {name || 'Guest'}!</Text>
    </View>
  );
}

export default NameInput;

As the user types, setName updates the state. The greeting uses the latest value on the next render. If the input is empty, the greeting displays Guest.

9. Managing Multiple State Variables

A component can call useState multiple times to manage independent pieces of information. Separate state variables are useful when values have different purposes or update independently.

9.1 Example: Login Form

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

function LoginForm() {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [message, setMessage] = useState('');

  function handleLogin() {
    if (!email.trim() || !password) {
      setMessage('Please enter your email and password.');
      return;
    }

    setMessage('Form details entered successfully.');
  }

  return (
    <View>
      <Text>Email</Text>
      <TextInput
        value={email}
        onChangeText={setEmail}
        placeholder="Enter email"
        keyboardType="email-address"
        autoCapitalize="none"
      />
      <Text>Password</Text>
      <TextInput
        value={password}
        onChangeText={setPassword}
        placeholder="Enter password"
        secureTextEntry
      />
      <Button title="Validate Form" onPress={handleLogin} />
      <Text>{message}</Text>
    </View>
  );
}

export default LoginForm;

This example demonstrates local form state and basic input validation. It does not authenticate a user or send credentials to a server.

9.2 Separate State vs Combined State

Separate state variables can make independent values easier to understand. Related form fields may also be grouped into an object. Choose the structure that makes updates clear and avoids unnecessary duplication.

10. Managing Object State

Objects are useful for storing related values, such as a user's name, email address, and city. When updating an object stored in state, create a new object rather than mutating the existing one.

10.1 Example: User Profile

import React, { useState } from 'react';
import { View, Text, TextInput } from 'react-native';

function UserProfileForm() {
  const [user, setUser] = useState({
    name: '',
    email: '',
    city: '',
  });

  function updateField(field, value) {
    setUser(previousUser => ({
      ...previousUser,
      [field]: value,
    }));
  }

  return (
    <View>
      <Text>Name</Text>
      <TextInput
        value={user.name}
        onChangeText={value => updateField('name', value)}
        placeholder="Enter name"
      />
      <Text>Email</Text>
      <TextInput
        value={user.email}
        onChangeText={value => updateField('email', value)}
        placeholder="Enter email"
        keyboardType="email-address"
      />
      <Text>City</Text>
      <TextInput
        value={user.city}
        onChangeText={value => updateField('city', value)}
        placeholder="Enter city"
      />
      <Text>Profile: {user.name || 'Not provided'}</Text>
    </View>
  );
}

export default UserProfileForm;

10.2 Understanding the Spread Operator

The spread syntax ...previousUser copies the existing properties into a new object. The updated field is then assigned its new value.

setUser(previousUser => ({
  ...previousUser,
  city: 'Mumbai',
}));

This creates a new object with the existing properties preserved and the city updated.

10.3 Important Note About Nested Objects

The spread operator creates a shallow copy. If the state contains nested objects, update the relevant nested levels immutably as well. Do not assume that spreading the outer object automatically copies every nested object.

11. Managing Array State

Array state is useful for collections such as to-do items, shopping cart products, messages, and selected options. React state should be treated as read-only, so create a new array when adding, removing, or updating items.

11.1 Adding an Item

setItems(previousItems => [
  ...previousItems,
  newItem,
]);

11.2 Removing an Item

setItems(previousItems =>
  previousItems.filter(item => item.id !== itemId)
);

11.3 Updating an Item

setItems(previousItems =>
  previousItems.map(item =>
    item.id === itemId
      ? { ...item, completed: !item.completed }
      : item
  )
);

11.4 Example: Simple To-Do List

import React, { useState } from 'react';
import { View, Text, TextInput, Pressable, StyleSheet } from 'react-native';

function TodoApp() {
  const [taskText, setTaskText] = useState('');
  const [tasks, setTasks] = useState([]);

  function addTask() {
    const trimmedTask = taskText.trim();

    if (!trimmedTask) {
      return;
    }

    const newTask = {
      id: `${Date.now()}-${Math.random()}`,
      title: trimmedTask,
      completed: false,
    };

    setTasks(previousTasks => [...previousTasks, newTask]);
    setTaskText('');
  }

  function toggleTask(taskId) {
    setTasks(previousTasks =>
      previousTasks.map(task =>
        task.id === taskId
          ? { ...task, completed: !task.completed }
          : task
      )
    );
  }

  function removeTask(taskId) {
    setTasks(previousTasks =>
      previousTasks.filter(task => task.id !== taskId)
    );
  }

  return (
    <View style={styles.container}>
      <Text style={styles.heading}>My Tasks</Text>
      <TextInput
        style={styles.input}
        value={taskText}
        onChangeText={setTaskText}
        placeholder="Enter a task"
      />
      <Pressable style={styles.addButton} onPress={addTask}>
        <Text style={styles.buttonText}>Add Task</Text>
      </Pressable>
      {tasks.map(task => (
        <View key={task.id} style={styles.taskRow}>
          <Pressable
            style={styles.taskText}
            onPress={() => toggleTask(task.id)}
          >
            <Text>
              {task.completed ? '✓ ' : '○ '}
              {task.title}
            </Text>
          </Pressable>
          <Pressable onPress={() => removeTask(task.id)}>
            <Text>Delete</Text>
          </Pressable>
        </View>
      ))}
      {tasks.length === 0 && (
        <Text>No tasks yet. Add your first task.</Text>
      )}
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 16,
  },
  heading: {
    fontSize: 24,
    fontWeight: 'bold',
    marginBottom: 12,
  },
  input: {
    borderWidth: 1,
    borderColor: '#999999',
    borderRadius: 6,
    padding: 10,
    marginBottom: 10,
  },
  addButton: {
    backgroundColor: '#2563eb',
    padding: 12,
    alignItems: 'center',
    borderRadius: 6,
    marginBottom: 12,
  },
  buttonText: {
    color: '#ffffff',
    fontWeight: 'bold',
  },
  taskRow: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    paddingVertical: 10,
    borderBottomWidth: 1,
    borderBottomColor: '#dddddd',
  },
  taskText: {
    flex: 1,
    paddingRight: 12,
  },
});

export default TodoApp;

11.5 What This Project Demonstrates

  • taskText stores the current text input.
  • tasks stores the list of task objects.
  • addTask adds a new task without mutating the previous array.
  • toggleTask updates the selected task immutably.
  • removeTask creates a new array without the selected task.
  • Conditional rendering displays a message when the list is empty.
  • Each list item uses a key to help React identify it.

For production applications, use a dedicated unique ID strategy if tasks need stable identities across sessions. The timestamp-based identifier above is suitable only as a simple demonstration.

12. Conditional Rendering with State

Conditional rendering means displaying different UI depending on a condition. State is commonly used to control which interface elements appear.

12.1 Example: Show and Hide Content

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

function DetailsPanel() {
  const [isVisible, setIsVisible] = useState(false);

  return (
    <View>
      <Button
        title={isVisible ? 'Hide Details' : 'Show Details'}
        onPress={() => setIsVisible(value => !value)}
      />
      {isVisible && (
        <Text>These are the additional details.</Text>
      )}
    </View>
  );
}

export default DetailsPanel;

12.2 Common Conditional Rendering Patterns

  • Logical AND: {'condition && <Component />'} displays a component when the condition is true.
  • Ternary operator: {'condition ? <A /> : <B />'} chooses between two UI options.
  • Early return: A component can return a different UI when a condition is met.
  • Conditional props: State can determine whether a control is disabled or which label it displays.

13. Controlled Inputs and Form State

A controlled input receives its displayed value from React state. Its event handler updates that state when the user types. This gives the component control over the current input value.

13.1 Example: Search Input

import React, { useState } from 'react';
import { View, Text, TextInput } from 'react-native';

function SearchBox() {
  const [searchText, setSearchText] = useState('');

  return (
    <View>
      <TextInput
        value={searchText}
        onChangeText={setSearchText}
        placeholder="Search products"
      />
      <Text>Searching for: {searchText || 'Nothing yet'}</Text>
    </View>
  );
}

export default SearchBox;

13.2 Benefits of Controlled Inputs

  • The current input value is available in component state.
  • The application can validate or transform input values.
  • The interface can respond immediately to user input.
  • The input can be cleared or populated programmatically.
  • The application can display related feedback based on the current value.

14. State Management for Loading, Success, and Error States

Mobile applications often load data from APIs. State can track whether a request is in progress, whether data has been loaded, and whether an error occurred.

14.1 Example: Loading and Error Messages

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

function DataStatus() {
  const [status, setStatus] = useState('idle');

  function simulateRequest() {
    setStatus('loading');

    setTimeout(() => {
      setStatus('success');
    }, 1500);
  }

  return (
    <View>
      <Button title="Load Data" onPress={simulateRequest} />
      {status === 'loading' && (
        <ActivityIndicator size="large" />
      )}
      {status === 'success' && (
        <Text>Data loaded successfully.</Text>
      )}
      {status === 'error' && (
        <Text>Unable to load data.</Text>
      )}
    </View>
  );
}

export default DataStatus;

This example simulates a successful request. It does not call an API or set the status to error. In a real request, use appropriate asynchronous logic and error handling, and clean up timers or cancel work when necessary.

14.2 Separate State Values or One Status Value?

When an operation can be idle, loading, successful, or unsuccessful, a single status value can make the intended state explicit. Separate Boolean variables can work for simple cases, but several independent Booleans may accidentally represent conflicting conditions, such as loading and success being true at the same time.

15. Lazy Initialization of State

If calculating the initial state is expensive, you can pass an initializer function to useState. React calls that initializer to determine the initial value rather than requiring the calculation to be repeated as an argument on every render.

15.1 Example

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

function createInitialCount() {
  return 10;
}

function Counter() {
  const [count, setCount] = useState(createInitialCount);

  return (
    <View>
      <Text>Count: {count}</Text>
    </View>
  );
}

export default Counter;

Notice that the function is passed as createInitialCount, not called as createInitialCount(). The initializer should be pure because React may invoke it more than once in development to check for unintended side effects.

16. Rules of the useState Hook

React Hooks must follow specific rules so React can consistently associate Hook calls with the correct component state.

  • Call at the top level: Call useState directly inside a function component or custom Hook.
  • Do not call inside conditions: Avoid placing Hook calls inside if statements or conditional branches.
  • Do not call inside loops: Keep Hook calls out of loops.
  • Do not call inside nested functions: Event handlers may call state setters, but should not call useState.
  • Use React function components or custom Hooks: Do not call Hooks from ordinary utility functions.
  • Keep state updates immutable: Replace arrays and objects rather than modifying them in place.
  • Use meaningful initial values: Choose values that reflect the intended data type and initial UI.

17. Common Mistakes When Using useState

Mistake Why It Is a Problem Correct Approach
Directly assigning to state It does not request a React state update. Call the setter returned by useState.
Mutating an object The same object reference is reused and changes can be missed or cause unpredictable behavior. Create a new object with the changed properties.
Mutating an array Methods such as push() or splice() change the existing array. Use operations such as map(), filter(), and array spreading to create a new array.
Assuming the setter changes the current variable immediately The running function still sees the state from its current render. Use the updated state in a subsequent render or calculate the next value explicitly.
Using stale state for repeated updates Several updates may calculate from the same render value. Use a functional updater when the next value depends on the previous value.
Calling Hooks conditionally It violates the Rules of Hooks. Call Hooks at the top level of the component.
Duplicating derived data in state Separate values can become inconsistent when one changes. Calculate values from existing props or state when practical.
Storing too much unrelated data in one object Updates can become harder to reason about. Choose separate or grouped state according to how the data is related.
Using state for values that never change It adds unnecessary complexity. Use a regular constant for fixed values that do not need to trigger rendering.

18. Props vs State

Props and state both influence what a component renders, but they have different roles. Props configure a component through inputs from its parent, while state stores information managed by the component or its state owner.

Basis Props State
Purpose Pass data or callbacks into a component. Store information that can change over time.
Source Usually supplied by a parent. Initialized and updated through React state APIs.
Updating The receiving component does not directly modify props. Updated using a setter such as setCount.
Example A product name passed to ProductCard. Whether a product is selected by the user.
Rendering Changes from the parent can cause a new render. State updates can cause a new render.

19. When Should You Use useState?

useState is best suited to state that belongs to a component or a small part of the UI. It is especially useful for simple, local interactions.

  • Counter values.
  • Text input values.
  • Checkbox or switch selections.
  • Expanded and collapsed sections.
  • Selected tabs or filters.
  • Small lists and collections.
  • Loading, success, and error indicators.
  • Temporary modal visibility.

19.1 When Might You Need Another Approach?

As an application grows, some state may need to be shared across many components or updated through complex rules. Depending on the requirements, alternatives or additional tools may include:

  • Lifted state: Move state to the nearest shared parent when multiple child components need the same value.
  • Context: Share values with distant descendants without passing props through every intermediate component.
  • useReducer: Organize more complex state transitions in a reducer function.
  • Dedicated state libraries: Consider a library when the application has broader shared-state requirements.
  • Server-state tools: Use suitable data-fetching and caching approaches when managing remote data.

These approaches do not replace useState in every situation. Choose the simplest state solution that meets the application's requirements.

20. Mini Project: Shopping Cart Quantity Manager

Create a simple shopping cart component that lets users increase or decrease the quantity of a product. This project combines number state, functional updates, conditional logic, and derived values.

20.1 Project Requirements

  • Display a product name and unit price.
  • Store the quantity using useState.
  • Provide Increase and Decrease buttons.
  • Prevent the quantity from falling below zero.
  • Calculate the total price from the unit price and quantity.
  • Display an empty-cart message when the quantity is zero.

20.2 Example Implementation

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

function ShoppingCart() {
  const [quantity, setQuantity] = useState(1);
  const unitPrice = 500;
  const totalPrice = quantity * unitPrice;

  function increaseQuantity() {
    setQuantity(previousQuantity => previousQuantity + 1);
  }

  function decreaseQuantity() {
    setQuantity(previousQuantity =>
      Math.max(0, previousQuantity - 1)
    );
  }

  return (
    <View style={styles.container}>
      <Text style={styles.heading}>Shopping Cart</Text>
      <Text>Product: Notebook</Text>
      <Text>Unit Price: ₹{unitPrice}</Text>
      <Text>Quantity: {quantity}</Text>
      <View style={styles.button}>
        <Button title="Increase Quantity" onPress={increaseQuantity} />
      </View>
      <View style={styles.button}>
        <Button
          title="Decrease Quantity"
          onPress={decreaseQuantity}
          disabled={quantity === 0}
        />
      </View>
      {quantity === 0 ? (
        <Text>Your cart is empty.</Text>
      ) : (
        <Text style={styles.total}>Total: ₹{totalPrice}</Text>
      )}
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 20,
  },
  heading: {
    fontSize: 24,
    fontWeight: 'bold',
    marginBottom: 12,
  },
  button: {
    marginVertical: 6,
  },
  total: {
    fontSize: 18,
    fontWeight: 'bold',
    marginTop: 12,
  },
});

export default ShoppingCart;

20.3 Project Explanation

  1. The quantity starts at one.
  2. The Increase button uses a functional state update to add one.
  3. The Decrease button subtracts one but never allows the quantity to fall below zero.
  4. The total price is calculated from the current quantity and the fixed unit price.
  5. The total price is derived during rendering instead of being stored in a second state variable.
  6. Conditional rendering shows an empty-cart message when the quantity reaches zero.

21. Practice Exercises

  1. Create a counter that starts at zero and has Increase, Decrease, and Reset buttons.
  2. Create a text input that displays the user's name as they type.
  3. Create a Boolean state variable to show or hide a paragraph.
  4. Build a password visibility toggle using secureTextEntry.
  5. Create a form with name, email, and city fields using object state.
  6. Create a task list that supports adding and deleting tasks.
  7. Add a completion toggle to each task in the task list.
  8. Build a product quantity selector that cannot go below zero.
  9. Create a screen with loading, success, and error states.
  10. Explain why state objects and arrays should be updated immutably.
  11. Demonstrate the difference between setCount(count + 1) and setCount(previous => previous + 1).
  12. Explain why calling a state setter does not immediately change the state variable in the current render.

22. Interview Questions and Answers

Q1. What is state in React Native?

Answer: State is information maintained by React that a component can use between renders. Updating state can cause the component to render again.

Q2. What is the useState Hook?

Answer: useState is a React Hook that declares a state variable and provides a setter function to request state updates.

Q3. What does useState return?

Answer: It returns an array containing the current state value and a setter function.

Q4. How do you import useState?

Answer: Use import { useState } from 'react';.

Q5. Can a component have multiple useState calls?

Answer: Yes. A component can use multiple state variables to manage independent pieces of information.

Q6. What data types can useState store?

Answer: It can store numbers, strings, Booleans, arrays, objects, null, and other JavaScript values.

Q7. Why should you not update state directly?

Answer: Direct mutation does not correctly request a React state update and can lead to unexpected rendering behavior. Use the setter function and immutable updates.

Q8. What is a functional state update?

Answer: It passes a function to the setter. The function receives the previous state and returns the next state.

Q9. When should you use a functional updater?

Answer: Use it when the next state depends on the previous state, such as incrementing a counter or toggling a Boolean.

Q10. What happens after a state update?

Answer: React schedules an update and renders the component using the latest state when the update is processed.

Q11. Why should arrays in state be updated immutably?

Answer: Creating a new array makes state changes explicit and avoids modifying the previous state value.

Q12. How do you update one property in an object state?

Answer: Create a new object using the spread operator and override the property that needs to change.

Q13. What is conditional rendering?

Answer: Conditional rendering displays different UI elements based on a condition, often using state.

Q14. Can useState be called inside an if statement?

Answer: No. Hooks must be called at the top level of a function component or custom Hook, not inside conditions or loops.

Q15. What is the difference between props and state?

Answer: Props are inputs supplied to a component, usually by its parent. State is information managed through React's state APIs and can change over time.

Q16. Should a calculated total price be stored in state?

Answer: If the total can be calculated directly from existing state and fixed values, calculate it during rendering instead of storing duplicate state that could become inconsistent.

23. Quick Revision Checklist

  • Understand state management and its purpose.
  • Import useState from React.
  • Declare state using const [value, setValue] = useState(initialValue).
  • Choose appropriate initial values.
  • Update state through its setter function.
  • Use functional updaters when the next value depends on the previous value.
  • Manage number, string, Boolean, array, and object state.
  • Update objects and arrays immutably.
  • Use state to control form inputs and user interactions.
  • Apply conditional rendering for different UI states.
  • Follow the Rules of Hooks.
  • Avoid unnecessary duplicate or derived state.
  • Understand the difference between props and state.
  • Build a small project to practise state updates.

24. Conclusion

The useState Hook is one of the fundamental tools for managing local state in React Native. It allows functional components to remember values between renders and update the interface in response to user actions.

By understanding initial values, setter functions, functional updates, immutable object and array updates, and conditional rendering, developers can build interactive forms, counters, lists, settings screens, and shopping cart interfaces.

Start with simple examples and gradually combine multiple state variables into complete mobile screens. As application requirements grow, learn when to lift state to a shared parent or use other state management techniques for more complex situations.

Continue Learning: Explore the React Native Training Course, visit the JustAcademy website, or register for a course demo.

whatsapp