{"id":21281904,"url":"https://github.com/guypeer8/hooxigene","last_synced_at":"2025-07-11T10:34:01.878Z","repository":{"id":57266615,"uuid":"171671696","full_name":"guypeer8/hooxigene","owner":"guypeer8","description":":thought_balloon: An unfancy straight forward state manager for react hooks applications","archived":false,"fork":false,"pushed_at":"2019-02-21T10:04:58.000Z","size":17,"stargazers_count":5,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-11-02T21:51:32.590Z","etag":null,"topics":["immer","react","react-hooks","reducer","redux","state-management"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/hooxigene","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/guypeer8.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-02-20T12:45:29.000Z","updated_at":"2020-01-27T21:33:18.000Z","dependencies_parsed_at":"2022-08-25T03:41:10.073Z","dependency_job_id":null,"html_url":"https://github.com/guypeer8/hooxigene","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/guypeer8%2Fhooxigene","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/guypeer8%2Fhooxigene/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/guypeer8%2Fhooxigene/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/guypeer8%2Fhooxigene/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/guypeer8","download_url":"https://codeload.github.com/guypeer8/hooxigene/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225715930,"owners_count":17512909,"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":["immer","react","react-hooks","reducer","redux","state-management"],"created_at":"2024-11-21T10:52:10.025Z","updated_at":"2024-11-21T10:52:10.653Z","avatar_url":"https://github.com/guypeer8.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"![cdbc0131-98f9-41a3-939e-07e23c1c2473](https://user-images.githubusercontent.com/13187428/53160489-bf45c080-35d0-11e9-818c-88bc234950cd.png)\n- An unfancy straight forward state manager for react hooks applications.\n\n## Installation\n```\nnpm install --save hooxigene\n```\n\n## Usage \n#### Create pretty \u0026 easy-to-understand reducer-like objects\n###### Notice that it seems like you \"mutate\" the data you change. You treat it as if it was a mutation in your code, but thanks to the power of `immer`, a new state object is created.\n```js\n// baseReducer.js\nexport default {\n    name: 'base',\n    initialState: {\n        modal: null,\n    },\n    handlers: {\n        SET_MODAL: (state, { modal }) =\u003e\n            state.modal = modal,\n        CLOSE: state =\u003e\n            state.modal = null,\n    },\n};\n\n// userReducer.js\nexport default {\n    name: 'user',\n    initialState: {\n        id: '',\n        local: {\n            email: '',\n            name: '',\n            password: '',\n            confirm_password: '',\n        },\n        plan: 'free',\n        active: true,\n        is_logged_in: false,\n        role: null,\n        error: {\n            message: '',\n            type: '',\n        },\n    },\n    handlers: {\n        CHANGE_FIELD: (state, payload) =\u003e\n            state.local = { ...state.local, ...payload },\n        SET_USER: (state, { id, role }) =\u003e {\n            state.id = id;\n            state.role = role;\n            state.is_logged_in = true;\n        },\n        LOGIN: state =\u003e\n            state.is_logged_in = true,\n        LOGOUT: state =\u003e {\n            state.id = '';\n            state.is_logged_in = false;\n            state.role = null;\n        },\n        SET_ADMIN: state =\u003e\n            state.role = 'admin',\n        SET_ERROR: (state, { error }) =\u003e\n            state.error = error,\n        CLEAR_ERROR: state =\u003e\n            state.error = { ...state.error, type: '', message: '' },\n        TOGGLE_ACTIVATION: state =\u003e\n            state.active = !state.active,\n    },\n};\n\n// dashboardReducer.js\nexport default {\n    name: 'dashboard',\n    initialState: {\n        siteId: null,\n        textEditor: {\n            mode: 'edit', // [ edit, preview ]\n        },\n        category: {\n            activeCategory: null,\n            list: {}, // { [category]: [] }\n        },\n        dictionary: {\n            currentPhrase: '',\n            defByPhrase: {},\n        },\n    },\n    handlers: {\n        SET_SITE_ID: (state, { site_id }) =\u003e\n            state.siteId = site_id,\n        SET_TEXT_EDITOR_MODE: (state, { mode }) =\u003e\n            state.textEditor.mode = mode,\n        SET_ACTIVE_CATEGORY: (state, { activeCategory }) =\u003e\n            state.category.activeCategory = activeCategory,\n        ADD_CATEGORY: (state, { category }) =\u003e\n            state.category.list[category] = [],\n        REMOVE_CATEGORY: (state, { category }) =\u003e\n            delete state.category.list[category],\n        ADD_SUBCATEGORY: (state, { category, subCategory }) =\u003e\n            state.category.list[category].push(subCategory),\n        ...\n        ...\n        ...\n    },\n};\n\n```\n#### Create your store passing your reducer-like objects using `createStore`\n```js\n// store.js\nimport { createStore } from 'hooxigene';\nimport dashboard from './dashboardReducer';\nimport base from './baseReducer';\nimport user from './userReducer';\n\nexport default createStore(base, user, dashboard);\n```\n---\n\n#### `StoreProvider`\n```js\n// index.js\nimport React from 'react';\nimport ReactDOM from 'react-dom';\nimport StoreProvider from 'hooxigene';\nimport AppRouter from './AppRouter';\nimport store from './store';\n\nconst App = () =\u003e (\n    \u003cStoreProvider \n        store={store}\n        viewer={true}\n     /\u003e  \n        \u003cAppRouter/\u003e\n    \u003c/StoreProvider\u003e\n);\n\nReactDOM.render(\n    \u003cApp/\u003e,\n    document.getElementById('root')\n);\n```\n- `StoreProvider` should wrap the app in the top level, so the store data will be available throughout the whole app.\n- `props`:\n  - `store` - pass a store holding the app state. the store should be created using the `createStore` function supplied be `hooxigene`.\n  - `viewer` - `hooxigene` uses `react-state-trace` library, which is a great devtool that let's you view your app state as it changes and break it to pieces. `viewer` is a boolean flag. when explicitly set to `true`, it shows the viewer at the top right of the app. Press `shift + s` to show or hide the devtool when you use it.\n---\n\n### Consuming the store \u0026 dispatching actions - `getState` \u0026 `getDispatch`\n```js\nimport React from 'react';\nimport capitalize from 'lodash/capitalize';\nimport { getState, getDispatch } from 'hooxigene';\n\nconst MODES = {\n    EDIT: 'edit',\n    PREVIEW: 'preview',\n};\n\nconst TextEditor = () =\u003e {\n    const mode = getState('dashboard.textEditor.mode');\n    const dispatch = getDispatch('dashboard');\n\n    return (\n        \u003cdiv\u003e\n            {Object.keys(MODES).map(MODE =\u003e (\n                \u003cbutton\n                    key={MODES[MODE]}\n                    active={mode === MODES[MODE]}\n                    onClick={() =\u003e\n                        dispatch('SET_TEXT_EDITOR_MODE', { mode: MODES[MODE] })\n                    }\n                \u003e{capitalize(MODES[MODE])} Mode\n                \u003c/button\u003e\n            ))}\n        \u003c/div\u003e\n    );\n};\n\nexport default TextEditor;\n```\n- `getState` exposes your app state. Make sure to call it inside a component or a function, because the nature of `hooks` in `react` require it.\n    - You pass the name you gave the reducer-like object. In our example it could be `dashboard`, `user` or `base`.\n    - If you have nested properties you do not have to destructure the object, you can simply separate the path using commas `.`. For example you can do any of the following four and it is the same:\n        - `const mode = getState('dashboard.textEditor.mode');`\n        - `const { mode } = getState('dashboard.textEditor');`\n        - `const { textEditor: { mode } } = getState('dashboard');`\n        - `const { dashboard: { textEditor: { mode } } } = getState();`\n    - When you use `getState` without a reducer-like object name, you get the whole state object.\n    \n- `getDispatch` exposes your app dispatcher / actions. As with `getState`, make sure to call it inside a component or a function.\n                    - You pass the name you gave the reducer-like object. In our example it could be `dashboard`, `user` or `base`.:\n    - You pass the name you gave the reducer-like object. In our example it could be `dashboard`, `user` or `base`.\n    - You can access a specific reducer-like object dispatcher directly. For example you can do any of the following four and it is the same:\n        - `const dispatch = getDispatch('dashboard');`\n        - `const dispatch = getDispatch().dashboard;`\n    - When you want to dispatch an action to change the state you call `dispatch('SET_TEXT_EDITOR_MODE', { mode: 'edit' })`.\n        - First argument is the type of the action which you defined as a key on `handlers` in your reducer-like object.\n        - Second argument is the payload which is passed to the handler itself as the second parameter: `handlers: { SET_TEXT_EDITOR_MODE: (state, { mode }) =\u003e state.mode = mode, }`.\n---\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fguypeer8%2Fhooxigene","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fguypeer8%2Fhooxigene","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fguypeer8%2Fhooxigene/lists"}