{"id":26348352,"url":"https://github.com/sandylib/react-hooker-boilerplate","last_synced_at":"2025-03-16T08:14:40.041Z","repository":{"id":35094886,"uuid":"205990629","full_name":"sandylib/react-hooker-boilerplate","owner":"sandylib","description":"react-hooker-boilerplate : You could use this quickly setup for react hook working with context api and use multiply reducer applications. No more redux needed anymore.","archived":false,"fork":false,"pushed_at":"2023-01-04T09:29:54.000Z","size":2467,"stargazers_count":0,"open_issues_count":24,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-01T15:05:00.190Z","etag":null,"topics":["context-api","react-hooks-demo","react-hooks-project","react-hooks-store","react-router-dom","reacthooks","usereducer"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sandylib.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-09-03T04:44:06.000Z","updated_at":"2020-09-22T11:51:28.000Z","dependencies_parsed_at":"2023-01-15T13:43:59.703Z","dependency_job_id":null,"html_url":"https://github.com/sandylib/react-hooker-boilerplate","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sandylib%2Freact-hooker-boilerplate","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sandylib%2Freact-hooker-boilerplate/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sandylib%2Freact-hooker-boilerplate/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sandylib%2Freact-hooker-boilerplate/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sandylib","download_url":"https://codeload.github.com/sandylib/react-hooker-boilerplate/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243841191,"owners_count":20356446,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["context-api","react-hooks-demo","react-hooks-project","react-hooks-store","react-router-dom","reacthooks","usereducer"],"created_at":"2025-03-16T08:14:39.490Z","updated_at":"2025-03-16T08:14:40.028Z","avatar_url":"https://github.com/sandylib.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).\n\n## React hook boilerplate is redux like application but no redux\n\nYou could use this quickly setup for react hook working with context api and use multiply reducer applications. No more redux needed anymore.\n\n![Sample](./src/sample.png?raw=true \"Book component\")\n\nIn the project directory, you can run:\n\n### `npm start`\n\n\n## The Setup\n\nMake sure you have Nodejs installed on your machine (I’m using version v12.6.0) and we’ll put the app together using,\ncreate-react-app:\n`$ npx create-react-app react-hooker-boilerplate`\n\nOnce it’s done, start it by running `$ npm start` in your project directory.\nThen open the package.json file. require node version 16.8 above \n\n## The \"react-hooker-boilerplate\" will follow Redux three fundamental **principles**, **stores**, **actions**, and **reducers**. But build by useing context api working with useReducer\n\n### `npm i react-router-dom`\n\n- let's start from create a store first, I have create configureStore.js under store folder\n\n```javascript\nimport React, {createContext, useContext, useReducer} from 'react';\n\nimport rootReducer, { initialState } from '../reducers/index';\n\nconst StateContext = createContext();\nconst DispatchContext = createContext();\n\nexport const useStateValue = () =\u003e useContext(StateContext);\nexport const useDispatch = () =\u003e useContext(DispatchContext);\n\nfunction Store(props) {\n    \n    const [state, dispatch] = useReducer(rootReducer, initialState);\n    \n    return (\n       \u003cDispatchContext.Provider value={dispatch}\u003e\n        \u003cStateContext.Provider value={state}\u003e\n           {props.children}\n        \u003c/StateContext.Provider\u003e\n      \u003c/DispatchContext.Provider\u003e\n    );\n  }\n\n\nexport default Store;\n\n```\n\n- since application grow will handle more and more complex state, so I create two separate reducer as example how to handle them \n\n- userReducer\n\n```javascript\n\nimport { UPDATE_SELECTED_USER } from '../constants/actionConstants';\n\n\nconst userReducer = (state, action) =\u003e {\n    switch (action.type) {\n        case UPDATE_SELECTED_USER: \n            return {\n                ...state,\n                selected: action.selected\n            }\n  \n        default:\n            return state;\n    }\n  }\n  \n  export default userReducer;\n\n```\n\n- bookReducer\n\n```javascript\n    import { UPDATE_SELECTED_BOOK } from '../constants/actionConstants';\n\n    const bookReducer = (state, action) =\u003e {\n    switch (action.type) {\n        case UPDATE_SELECTED_BOOK:\n            return {\n                ...state,\n                selected: action.selected\n            }\n\n        default:\n        return state;\n    }\n    }\n\n    export default bookReducer;\n```\n\n\n- rootReducer\n\n```javascript\n    import bookReducer from './bookReducer';\n    import userReducer from './userReducer';\n\n    const rootReducer = ({book, user}, action) =\u003e {\n        // middleware goes here, i.e calling analytics service, etc.\n    \n        return {\n            book: bookReducer(book, action),\n            user: userReducer(user, action)\n        }\n    }\n\n    export const initialState = {\n        user: {\n            list: [\n                {\n                \"balance\": \"$3,946.45\",\n                \"picture\": \"http://placehold.it/32x32\",\n                \"age\": 23,\n                \"name\": \"Bird Ramsey\",\n                \"gender\": \"male\",\n                \"company\": \"NIMON\",\n                \"email\": \"birdramsey@nimon.com\"\n                },\n            ....\n            \n                ],\n        selected: null\n        },\n        book: {\n        selected: null,\n        list: [\n            {\n            \"author\": \"Chinua Achebe\",\n            \"country\": \"Nigeria\",\n            \"imageLink\": \"images/things-fall-apart.jpg\",\n            \"language\": \"English\",\n            \"link\": \"https://en.wikipedia.org/wiki/Things_Fall_Apart\\n\",\n            \"pages\": 209,\n            \"title\": \"Things Fall Apart\",\n            \"year\": 1958\n            },\n            ...\n            ]\n        }\n    }\n\n    export default rootReducer;\n\n```\n\n- action that work exactly like redux\n\n```javascript\n    import { UPDATE_SELECTED_USER } from  '../constants/actionConstants';\n\n    export const updateSelectedUser = (dispatch, user) =\u003e \n        dispatch ({\n            type: UPDATE_SELECTED_USER,\n            selected: user\n        })\n\n```\n\n- UserComponent build in react hook and reader data from your stor and fire action\n\n```javascript\n    import React from 'react'\n    import { useStateValue, useDispatch } from '../../store/configureStore';\n    import { updateSelectedUser } from '../../reducers/user.action';\n\n    const UserInfo = ({user, selected, onClick}) =\u003e {\n\n        const handleClick = (user) =\u003e e =\u003e {\n            onClick(user);\n        };\n\n        return (\n        \u003ctr \n            onClick={handleClick(user)} \n            className={`${user === selected ? 'hightlight' : '' }`}\n        \u003e\n            \u003ctd\u003e{user.balance}\u003c/td\u003e\n            \u003ctd\u003e\u003cimg src={user.picture} width={60} height={80}/\u003e\u003c/td\u003e\n            \u003ctd\u003e{user.age}\u003c/td\u003e\n            \u003ctd\u003e{user.name}\u003c/td\u003e\n            \u003ctd\u003e{user.gender}\u003c/td\u003e\n            \u003ctd\u003e{user.company}\u003c/td\u003e\n            \u003ctd\u003e{user.email}\u003c/td\u003e\n        \u003c/tr\u003e\n        )\n\n\n    }\n\n\n    export default function UserComponent() {\n        const {user} = useStateValue();\n\n        const {list, selected} = user;\n\n        const dispatch = useDispatch();\n\n        const handleOnClick = user =\u003e updateSelectedUser(dispatch, user);\n        \n        return (\n            \u003ctable\u003e\n            \u003ctbody\u003e\n            \u003ctr\u003e\n                \u003cth\u003ebalance\u003c/th\u003e\n                \u003cth\u003epicture\u003c/th\u003e\n                \u003cth\u003eage\u003c/th\u003e\n                \u003cth\u003ename\u003c/th\u003e\n                \u003cth\u003egender\u003c/th\u003e\n                \u003cth\u003ecompany\u003c/th\u003e\n                \u003cth\u003eemail\u003c/th\u003e\n            \u003c/tr\u003e\n\n            {list.map( (item, idx) =\u003e \u003cUserInfo key={idx} user={item} selected={selected} onClick={handleOnClick} /\u003e )}\n            \u003c/tbody\u003e\n        \u003c/table\u003e\n        )\n    }\n\n```\n\n- appRouter.js\n\n```javascript\n\nimport React from 'react';\nimport { BrowserRouter as Router, Route, Link } from \"react-router-dom\";\n\nimport {\n    BookComponent,\n    UserComponent,\n    Home\n} from './components/';\n\n\nconst  AppRouter = () =\u003e {\n    return (\n        \u003cRouter\u003e\n            \u003cdiv\u003e\n\n            \u003cul\u003e\n          \u003cli\u003e\n            \u003cLink to=\"/\"\u003eHome\u003c/Link\u003e\n          \u003c/li\u003e\n          \u003cli\u003e\n            \u003cLink to=\"/user\"\u003eUser\u003c/Link\u003e\n          \u003c/li\u003e\n          \u003cli\u003e\n            \u003cLink to=\"/book\"\u003eBook\u003c/Link\u003e\n          \u003c/li\u003e\n        \u003c/ul\u003e\n\n        \u003chr /\u003e\n            \n           \n\n            \u003cRoute exact path=\"/\" component={Home} /\u003e\n            \u003cRoute path=\"/user\" component={UserComponent} /\u003e\n            \u003cRoute path=\"/book\" component={BookComponent} /\u003e\n            \u003c/div\u003e\n            \n        \u003c/Router\u003e\n    )\n}\n\nexport default AppRouter;\n\n\n```\n\n- App.js\n\n```javascript\n\nimport React from 'react';\nimport AppRouter from './AppRouter';\nimport './App.css';\nimport Store from './store/configureStore';\n\nfunction App() {\n  return (\n    \u003cStore\u003e\n      \u003cAppRouter/\u003e\n   \u003c/Store\u003e\n  );\n}\n\nexport default App;\n\n\n```\n\n- middleware that could be build a separeat file and put it into my rootReduce\n\n```javascript\nconst rootReducer = ({book, user}, action) =\u003e {\n    // middleware goes here, i.e calling analytics service, etc.\n   \n    return {\n        book: bookReducer(book, action),\n        user: userReducer(user, action)\n    }\n}\n\n```\n\n\n\n## Conclusion\n\nAs you can see with the power of the context api and react hooks it can entirely get rid of redux but working like redux application. \n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsandylib%2Freact-hooker-boilerplate","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsandylib%2Freact-hooker-boilerplate","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsandylib%2Freact-hooker-boilerplate/lists"}