Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
File renamed without changes.
48 changes: 37 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# GX - Global State Management for React Applications

`React` and `React Native` Library for managing global state.

[![npm version](https://badge.fury.io/js/%40dilane3%2Fgx.svg)](https://badge.fury.io/js/%40dilane3%2Fgx)
[![npm downloads](https://img.shields.io/npm/dm/%40dilane3%2Fgx)](https://www.npmjs.com/package/@dilane3/gx)
[![GitHub license](https://img.shields.io/github/license/react-gx/gx)](https://github.com/react-gx/gx/blob/main/LICENSE)


![logo](./assets/logo.png)

This library aims to provide you an `easy` and `fast` way to set up and manage the global state of your **`react`** application.
Expand All @@ -11,13 +18,13 @@ You can use `npm` or `yarn` to install this library into your react application.
### Using npm

```bash
npm install gx
npm install @dilane3/gx
```

### Using yarn

```bash
yarn add gx
yarn add @dilane3/gx
```

## Prerequisites
Expand All @@ -40,6 +47,8 @@ function App() {
</StrictMode>
);
}

export default App;
```

**After**
Expand All @@ -56,6 +65,8 @@ function App() {
</Fragment>
);
}

export default App;
```

### Disabling strict mode on Next.js
Expand Down Expand Up @@ -113,7 +124,7 @@ Here is the result.
Inside the `signals` directory, create a file called `counter.js` for example.

```js
import { createSignal } from 'gx';
import { createSignal } from '@dilane3/gx';

const counterSignal = createSignal({
name: 'counter',
Expand All @@ -137,7 +148,7 @@ export default counterSignal;
Inside the `store` directory, create an `index.js` file.

```js
import { createStore } from "gx";
import { createStore } from "@dilane3/gx";
import counterSignal from "../signals/counter";

export default createStore([counterSignal]);
Expand All @@ -150,7 +161,7 @@ Inside your `App.js` file, import your store and wrap your application with the
```js
import React from "react";
import store from "./gx/store";
import GXProvider from "gx";
import GXProvider from "@dilane3/gx";

function App() {
return (
Expand All @@ -172,7 +183,7 @@ Create a component called `Counter` inside the Counter.js file. Then import two

```js
import React from "react";
import { useSignal, useAction } from "gx";
import { useSignal, useAction } from "@dilane3/gx";

function Counter() {
// State
Expand All @@ -192,6 +203,8 @@ function Counter() {
</div>
);
}

export default Counter;
```

Note that the `useSignal` hook takes the name of the signal as a parameter and return the state contained inside that signal.
Expand Down Expand Up @@ -261,12 +274,29 @@ const counter = useSignal("counter");

### `useAction`

This hook takes the name of the signal as a parameter and returns an object that contains all the actions of this signal.
This hook takes the name of the signal as a the first parameter and returns an object that contains all the actions of this signal.

```js
const { increment, decrement } = useAction("counter");
```

**`New in version 1.1.0`**

Note that, the `useAction` hook can accept a second parameter which is the list of actions that you want to use. If you don't specify the second parameter, all the actions of the signal will be returned.

There is another thing that you have to know.
If you provide only one action as a second parameter, the hook will return only the action itself and not an object that contains the action.

```js
const increment = useAction("counter", "increment");
```

And if you provide more than one action, the hook will return an object that contains all the actions provided.

```js
const { increment, decrement } = useAction("counter", "increment", "decrement");
```

## License

[MIT](https://choosealicense.com/licenses/mit/)
Expand All @@ -282,7 +312,3 @@ const { increment, decrement } = useAction("counter");

Contributions, issues and feature requests are welcome!
See the [Contributing Guide](./CONTRIBUTING.md).

## Keywords

react, state, management, hooks, gx
2 changes: 1 addition & 1 deletion dist/hooks/useAction.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
declare const useAction: (signalName: string) => {
declare const useAction: (signalName: string, ...actions: string[]) => ((payload: any) => void) | {
[key: string]: (payload: any) => void;
};
export default useAction;
40 changes: 33 additions & 7 deletions dist/hooks/useAction.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/hooks/useAction.js.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 4 additions & 13 deletions dist/providers/reducer.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/providers/reducer.js.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 29 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,21 @@
{
"name": "gx",
"version": "1.0.0",
"name": "@dilane3/gx",
"version": "1.1.0",
"private": false,
"license": "MIT",
"main": "dist/index.js",
"author": {
"name": "dilane3",
"email": "komboudilane125@gmail.com",
"url": "https://dilane3.com",
"twitter": "https://twitter.com/dilanekombou",
"github": "https://github.com/dilane3"
},
"repository": {
"type": "git",
"url": "https://github.com/react-gx/gx",
"issues": "https://github.com/react-gx/gx/issues"
},
"devDependencies": {
"@testing-library/jest-dom": "^5.14.1",
"@testing-library/react": "^13.0.0",
Expand All @@ -15,12 +27,26 @@
"typescript": "^4.4.2"
},
"peerDependencies": {
"react": "^18.2.0"
"react": "^18.0.0"
},
"scripts": {
"build": "tsc",
"test": "react-scripts test"
},
"keywords": [
"react",
"react-gx",
"gx",
"redux",
"zustand",
"mobx",
"management",
"state",
"state-management",
"react-state-management",
"global",
"global-state"
],
"eslintConfig": {
"extends": [
"react-app",
Expand Down
57 changes: 43 additions & 14 deletions src/hooks/useAction.ts
Original file line number Diff line number Diff line change
@@ -1,49 +1,78 @@
import { useContext, useState, useEffect } from 'react';
import { useContext, useState, useEffect } from "react";
import GXContext from "../contexts";
import { GXActionType } from "../contexts/types";


const useAction = (signalName: string) => {
const useAction = (signalName: string, ...actions: string[]) => {
// Get Global Context
const { signals, dispatch } = useContext(GXContext);

// Some handlers

/**
* Get actions of a signal
* @param signalName
* @returns
* @param signalName
* @returns
*/
const handleGetActions = (signalName: string) => {
const signal = signals.find(signal => signal.name === signalName);
const signal = signals.find((signal) => signal.name === signalName);

if (signal) {
return signal.actions;
}
if (!actions || actions.length === 0) return signal.actions;

const filteredActions : GXActionType<any>[] = [];

for (let action of actions) {
const actionName = `${signalName}/${action}`;

const retrievedAction = signal.actions.find((act) => act.type === actionName);

if (retrievedAction) filteredActions.push(retrievedAction);
else throw new Error(`Action ${actionName} not found`);
}

return [];
}
return filteredActions;
} else throw new Error(`Signal ${signalName} not found`);
};

const handleFormatActions = () => {
// Get actions
const nonFormattedActions = handleGetActions(signalName);

// Get number of actions
const numberOfActions = nonFormattedActions.length;

// Check if actions are only one
if (numberOfActions === 1) {
const action = nonFormattedActions[0];

// Return action as a function
return (payload: any) => {
dispatch({
type: action.type,
payload,
});
};
}

// If actions are more than one

// Formatted actions
const formattedActions: { [key: string]: (payload: any) => void } = {};

for (const action of nonFormattedActions) {
// Get action name
const actionName = action.type.split('/')[1];
const actionName = action.type.split("/")[1];

formattedActions[actionName] = (payload: any) => {
dispatch({
type: action.type,
payload
payload,
});
}
};
}

return formattedActions;
}
};

return handleFormatActions();
};
Expand Down
Loading