DEV Community

Cover image for How to Integrate Redux in React Native with the New Architecture
Amit Kumar
Amit Kumar

Posted on

How to Integrate Redux in React Native with the New Architecture

React Native’s New Architecture—powered by Fabric, TurboModules, and Codegen—enhances performance and improves the developer experience. But when it comes to global state management, Redux is still a go-to solution for many developers.

In this guide, we’ll walk through setting up Redux in a React Native project using a clean, scalable, and future-proof structure, fully compatible with the New Architecture.


📦 Step 0: Install Redux Packages

Let’s start by installing the essential Redux packages:

Using npm:

npm install @reduxjs/toolkit react-redux

Enter fullscreen mode Exit fullscreen mode

Or using yarn:

yarn add @reduxjs/toolkit react-redux

Enter fullscreen mode Exit fullscreen mode

@reduxjs/toolkit provides a modern Redux setup with less boilerplate.
react-redux connects your React Native components to the Redux store.


🗂 Folder Structure

We’ll organize Redux inside the src/ folder like this:

/src
  ├── /store
  │   ├── configureStore.js
  │   └── rootReducer.js
  ├── /services
  │   └── /app
  │       ├── reducer.js
  │       └── actions.js (optional)
  └── App.js

Enter fullscreen mode Exit fullscreen mode

⚙️ Step 1: Configure the Store

src/store/configureStore.js

import { configureStore } from '@reduxjs/toolkit';
import rootReducer from './rootReducer';

const store = configureStore({
  reducer: rootReducer,
  devTools: true,
  middleware: getDefaultMiddleware =>
    getDefaultMiddleware({
      serializableCheck: false, // Avoid warnings for non-serializable values like navigation
    }),
});

export default store;

Enter fullscreen mode Exit fullscreen mode

🧠 Step 2: Create Root Reducer

src/store/rootReducer.js

import { combineReducers } from '@reduxjs/toolkit';
import { appReducer } from '../services/app/reducer';

const combinedReducer = combineReducers({
  app: appReducer,
});

const rootReducer = (state, action) => {
  if (action.type === 'USER_LOGOUT') {
    state = undefined;
  }
  return combinedReducer(state, action);
};

export default rootReducer;

Enter fullscreen mode Exit fullscreen mode

This handles app-wide state reset on logout.


Step 3: Create Actions, Constants, and Reducers

Next, create folders and files for actions, constants, and reducers.

Create the following directory structure inside the store folder:

store/
  Home/
    action/
      index.js
    constant/
      index.js
    reducer/
      index.js

Enter fullscreen mode Exit fullscreen mode

Actions
Define your actions in store/Home/action/index.js.

// store/Home/action/index.js
import { TEST_NAME } from '../constant';

export const addValue = (text) => ({
  type: TEST_NAME,
  payload: text,
});

Enter fullscreen mode Exit fullscreen mode

Constants
Define your action types in store/Home/constant/index.js.

// store/Home/constant/index.js
export const TEST_NAME = 'TEST_NAME';

Enter fullscreen mode Exit fullscreen mode

Reducers
Handle the state changes in store/Home/reducer/index.js.

// store/Home/reducer/index.js
import { TEST_NAME } from '../constant';

const initialState = {
  value: '',
};

const inputValueReducer = (state = initialState, action) => {
  switch (action.type) {
    case TEST_NAME:
      return {
        ...state,
        value: action.payload,
      };
    default:
      return state;
  }
};

export default inputValueReducer;

Enter fullscreen mode Exit fullscreen mode

Step 4: Integrate Redux with React Native Components

Now, let's integrate Redux with a React Native component.

Home Screen
Create or modify a screen component to dispatch actions and read state from the Redux store.

// screens/Home.js
import React, { useState } from 'react';
import { Button, StyleSheet, Text, TextInput, View } from 'react-native';
import { useDispatch, useSelector } from 'react-redux';
import { TEST_NAME } from '../../store/Home/constant';

const Home = ({ navigation }) => {
  const [value, setValue] = useState('');
  const text = useSelector((state) => state.inputValueReducer.value);
  const dispatch = useDispatch();

  return (
    <View style={styles.container}>
      <Text onPress={() => navigation.navigate('Profile')}>Home</Text>
      <TextInput value={value} onChangeText={(text) => setValue(text)} style={styles.input} />
      <Button
        title='Send'
        onPress={() => {
          dispatch({ type: TEST_NAME, payload: value });
        }}
      />
      <Text>{text}</Text>
    </View>
  );
};

export default Home;

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  input: {
    borderColor: 'gray',
    borderWidth: 1,
    padding: 10,
    marginBottom: 10,
    width: '80%',
  },
});

Enter fullscreen mode Exit fullscreen mode

Step 5: Wrap Your Application with the Provider

Finally, wrap your application with the Provider component from react-redux to make the Redux store available to your entire app.

// App.js
import React from 'react';
import { Provider } from 'react-redux';
import store from './store/configStore';
import Home from './screens/Home';

const App = () => {
  return (
    <Provider store={store}>
      <Home />
    </Provider>
  );
};

export default App;

Enter fullscreen mode Exit fullscreen mode

Conclusion

By following these steps, you've successfully integrated Redux and Redux-Thunk into your React Native application. This setup provides a scalable architecture for managing state and handling asynchronous operations, making your application more robust and maintainable.

Top comments (1)

Collapse
 
dreama profile image
Dream

Nice guide! I see we’re still inviting Redux to every state party, huh? At least with all these folders, we won’t lose it in the coatroom. Any tips for not drowning in reducers as the app grows?