how-to-structure-a-typescript-project-with-react-and-redux.html

How to Structure a TypeScript Project with React and Redux

In the ever-evolving landscape of web development, TypeScript, React, and Redux have emerged as powerful tools for creating scalable applications. Combining the type safety of TypeScript with the component-based architecture of React and the state management capabilities of Redux can significantly enhance your development process. In this guide, we will explore how to structure a TypeScript project that leverages these technologies effectively.

Why Use TypeScript with React and Redux?

Benefits of TypeScript

  • Static Typing: TypeScript helps catch errors early in the development process, reducing runtime errors and improving code quality.
  • Enhanced IDE Support: TypeScript provides better autocompletion and navigation in IDEs, making the development experience smoother.
  • Improved Documentation: With TypeScript’s type annotations, your code becomes self-documenting, making it easier for new developers to understand.

Why React and Redux?

  • Component-Based Architecture: React’s component-based architecture facilitates reusability and better organization of code.
  • State Management: Redux offers a centralized state management solution that simplifies state transitions and debugging.

Setting Up Your Project

Step 1: Initialize Your Project

To begin, create a new TypeScript project using Create React App with TypeScript support. Open your terminal and run the following command:

npx create-react-app my-app --template typescript

This command sets up a new React project with TypeScript configured out of the box.

Step 2: Install Redux

Next, you need to install Redux along with its TypeScript typings. Run the following commands:

npm install redux react-redux
npm install @types/react-redux --save-dev

This installs the Redux library and the necessary types for React-Redux.

Project Structure

A well-structured project is crucial for maintainability. Here's a recommended folder structure for your TypeScript React-Redux app:

my-app/
├── public/
├── src/
│   ├── components/
│   ├── redux/
│   │   ├── actions/
│   │   ├── reducers/
│   │   └── store.ts
│   ├── types/
│   ├── App.tsx
│   ├── index.tsx
└── tsconfig.json

Detailed Folder Purpose

  • components/: Contains all your React components.
  • redux/: Holds Redux-related files.
  • actions/: Contains action creators that define how to change the state.
  • reducers/: Contains reducer functions that specify how the state changes in response to actions.
  • store.ts: Sets up the Redux store.
  • types/: Contains TypeScript interfaces and types to ensure type safety across your application.

Implementing Redux

Step 3: Create Actions

In the redux/actions/ directory, create a file named actionTypes.ts to define action types:

// redux/actions/actionTypes.ts
export const INCREMENT = 'INCREMENT';
export const DECREMENT = 'DECREMENT';

Next, create a file named counterActions.ts for the action creators:

// redux/actions/counterActions.ts
import { INCREMENT, DECREMENT } from './actionTypes';

export const increment = () => ({
    type: INCREMENT,
});

export const decrement = () => ({
    type: DECREMENT,
});

Step 4: Create Reducers

In the redux/reducers/ directory, create a file named counterReducer.ts:

// redux/reducers/counterReducer.ts
import { INCREMENT, DECREMENT } from '../actions/actionTypes';

interface CounterState {
    count: number;
}

const initialState: CounterState = {
    count: 0,
};

const counterReducer = (state = initialState, action: { type: string }): CounterState => {
    switch (action.type) {
        case INCREMENT:
            return { count: state.count + 1 };
        case DECREMENT:
            return { count: state.count - 1 };
        default:
            return state;
    }
};

export default counterReducer;

Step 5: Configure the Redux Store

Create a store.ts file in the redux/ directory to configure the Redux store:

// redux/store.ts
import { createStore, combineReducers } from 'redux';
import counterReducer from './reducers/counterReducer';

const rootReducer = combineReducers({
    counter: counterReducer,
});

const store = createStore(rootReducer);

export default store;

Step 6: Connect Redux with React

Now, you need to connect your Redux store with the React application. Modify the index.tsx file:

// src/index.tsx
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import store from './redux/store';
import App from './App';

ReactDOM.render(
    <Provider store={store}>
        <App />
    </Provider>,
    document.getElementById('root')
);

Step 7: Create a Component

Now, let’s create a simple counter component in the components/ directory. Create a file named Counter.tsx:

// src/components/Counter.tsx
import React from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { increment, decrement } from '../redux/actions/counterActions';

const Counter: React.FC = () => {
    const dispatch = useDispatch();
    const count = useSelector((state: { counter: { count: number } }) => state.counter.count);

    return (
        <div>
            <h1>{count}</h1>
            <button onClick={() => dispatch(increment())}>Increment</button>
            <button onClick={() => dispatch(decrement())}>Decrement</button>
        </div>
    );
};

export default Counter;

Finally, use the Counter component in your App.tsx:

// src/App.tsx
import React from 'react';
import Counter from './components/Counter';

const App: React.FC = () => {
    return (
        <div>
            <h1>TypeScript React Redux Counter</h1>
            <Counter />
        </div>
    );
};

export default App;

Conclusion

Structuring a TypeScript project with React and Redux may seem daunting at first, but by following this guide, you can set up a scalable and maintainable codebase. Leveraging TypeScript’s type safety, React’s powerful UI capabilities, and Redux’s state management will significantly enhance your development experience.

As you progress, consider exploring middleware like Redux Thunk or Redux Saga for handling asynchronous actions, which can further enrich your application’s capabilities. Happy coding!

SR
Syed
Rizwan

About the Author

Syed Rizwan is a Machine Learning Engineer with 5 years of experience in AI, IoT, and Industrial Automation.