- About
- Built using
- Project structure
- Getting started
- Project setup
- How to create a reducer?
- Contributing
- Versioning
- Authors
- License
A basic project structure to build React JS apps using Redux.
- React JS: JavaScript library
- Redux: A Predictable State Container for JS Apps
- TypeScript: JavaScript With Syntax For Types.
- Jest: JavaScript Testing Framework
- React Testing Library: Testing utilities
src ├── components │ └── Counter ├── hooks │ └── useCounter ├── redux │ ├── actions │ ├── constants │ ├── reducers │ ├── selectors │ └── store └── tests └── mocksYou need to install on your machine Node.js or Yarn.
npm install # or yarn install# start app open development mode yarn start # or npm run startyarn build # or npm run build# show errors yarn lint # or npm run lint # fix errors yarn lint:fix # or npm run lint:fix# run tests yarn test # or npm run test # run tests on watch mode yarn test:watch # or npm run test:watch # run tests on coverage mode yarn test:coverage # or npm run test:coverage # run tests on coverage with watch mode yarn test:coverage:watch # or npm run test:coverage:watchAs an example, let's implement a counter component reducer. Files are also available in the repository. Follow the steps below to implement your first reducer.
- Create action types constants, in the
constantsdirectory:
// src/redux/constants/counter.ts export const actionTypes = { COUNTER_DECREMENT: 'COUNTER_DECREMENT', COUNTER_INCREMENT: 'COUNTER_INCREMENT' }- Create reducer, in the
reducersdirectory:
// src/redux/reducers/counter.ts import { actionTypes } from '../constants/counter' type Action = { type: 'COUNTER_DECREMENT' | 'COUNTER_INCREMENT' } const INITIAL_STATE = { counter: 0 } export const counterReducers = (state = INITIAL_STATE, action: Action) => { switch (action.type) { case actionTypes.COUNTER_DECREMENT: return { ...state, counter: state.counter - 1 } case actionTypes.COUNTER_INCREMENT: return { ...state, counter: state.counter + 1 } default: return state } }- Import reducer on reducers main file:
// src/redux/reducers/index.ts import { combineReducers } from 'redux' import { counterReducers } from './counter' export const reducers = combineReducers({ // ... counterReducers })- Create action types methods, in the
actionsdirectory:
// src/redux/actions/counter.ts import { actionTypes } from '../constants/counter' export const actions = { decrement: () => ({ type: actionTypes.COUNTER_DECREMENT }), increment: () => ({ type: actionTypes.COUNTER_INCREMENT }) }- Create selectors, in the
selectorsdirectory:
// src/redux/selectors/counter.ts import { RootStateOrAny } from 'react-redux' export const selectors = { getCounter: (state: RootStateOrAny) => state.counterReducers.counter }- Create a custom hook, in the
hooksdirectory:
// src/hooks/useCounter/index.tsx import { useSelector, useDispatch } from 'react-redux' import { actions } from '../../redux/actions/counter' import { selectors } from '../../redux/selectors/counter' export function useCounter () { const counter = useSelector(selectors.getCounter) const dispatch = useDispatch() const handleDecrement = () => dispatch(actions.decrement()) const handleIncrement = () => dispatch(actions.increment()) return { counter, handleDecrement, handleIncrement } }- Import custom hook in the component:
// src/components/Counter/index.tsx import { useCounter } from '../../hooks/useCounter' export function Counter () { const { counter, handleDecrement, handleIncrement } = useCounter() return ( <div> <h1> Counter: {counter} </h1> <button onClick={handleDecrement}> Decrement </button> <button onClick={handleIncrement}> Increment </button> </div> ) }Please read CONTRIBUTING.md for details on our code of conduct, and the process for submitting pull requests to us.
We use SemVer for versioning. For the versions available, see the tags on this repository.
See also the list of contributors who participated in this project.
This project is licensed under the MIT License - see the LICENSE.md file for details
Develop by Eder Sampaio 👋 See my linkedin.