Skip to content
This repository was archived by the owner on Feb 14, 2023. It is now read-only.

Commit 9821b9f

Browse files
committed
resolves #60
1 parent 379a968 commit 9821b9f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+1123
-378
lines changed

Provider.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# Provider
22

3+
_Requires React >= 16.3.0_
4+
35
ReactN's global components attempt to receive the global state from a React
46
Context. If the ReactN Context cannot be found, then the global components will
57
fallback to a default global state.
@@ -84,15 +86,15 @@ Provider.resetGlobal();
8486

8587
Provider.setGlobal({ x: 1 });
8688

87-
Provider.useDispatch();
89+
Provider.useDispatch(); // Requires React >= 16.8.0
8890

89-
Provider.useDispatch('name');
91+
Provider.useDispatch('name'); // Requires React >= 16.8.0
9092

91-
Provider.useDispatch(reducerFunction);
93+
Provider.useDispatch(reducerFunction); // Requires React >= 16.8.0
9294

93-
Provider.useGlobal();
95+
Provider.useGlobal(); // Requires React >= 16.8.0
9496

95-
Provider.useGlobal('property');
97+
Provider.useGlobal('property'); // Requires React >= 16.8.0
9698
```
9799

98100
## useGlobal and withGlobal

README.md

Lines changed: 276 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,11 @@ with deeply nested objects, a
9797
* [removeCallback](#removecallback)
9898
* [resetGlobal](#resetglobal)
9999
* [setGlobal](#setglobal)
100+
* [useDispatch](#usedispatch)
101+
* [useGlobal](#useglobal)
100102
* [withGlobal](#withglobal)
101103
* [withInit](#withinit)
104+
* [Terminology](#terminology)
102105
* [Frequently Asked Questions](https://github.com/CharlesStover/reactn/blob/master/FAQ.md)
103106
* [Support](#support)
104107

@@ -681,6 +684,152 @@ setGlobal(
681684
);
682685
```
683686

687+
##### useDispatch
688+
689+
_Requires React >= 16.8.0_
690+
691+
The `useDispatch` helper function is a React Hook analogous to the `useReducer`
692+
hook built into React itself. `useDispatch` will dispatch a global reducer that
693+
has been added to ReactN via the [`addReducer`](#addreducer),
694+
[`addReducers`](#addreducers), or [`withInit`](#withinit) helper functions or a
695+
global reducer that you specify inline as a parameter.
696+
697+
###### useDispatch()
698+
699+
`useDispatch()` with no parameters will return a map of all of your global
700+
reducers.
701+
702+
```javascript
703+
import { useDispatch } from 'reactn';
704+
705+
function MyComponent() {
706+
const dispatch = useDispatch();
707+
dispatch.add(1);
708+
dispatch.substract(2);
709+
return null;
710+
}
711+
```
712+
713+
###### useDispatch(Function)
714+
715+
`useDispatch(f)` allows you to define your global reducer inline. This method
716+
is particularly useful if you prefer to import your reducers as needed or keep
717+
your singleton reducers with the components that use them.
718+
719+
```javascript
720+
import React, { useDispatch, useGlobal } from 'reactn';
721+
722+
function MyComponent() {
723+
const [ count ] = useGlobal('count');
724+
const add = useDispatch(
725+
(global, _dispatch, n) => ({
726+
count: global.count + n,
727+
}),
728+
);
729+
return (
730+
<button onClick={() => add(1)}>
731+
{count}.
732+
</span>
733+
);
734+
}
735+
```
736+
737+
###### useDispatch(Function, keyof State)
738+
739+
`useDispatch(f, 'property')` allows you to define your global property reducer
740+
inline. A property reducer changes only one property of the global state, which
741+
can greatly simplify your reducer logic.
742+
743+
```javascript
744+
import React, { useDispatch, useGlobal } from 'reactn';
745+
746+
function MyComponent() {
747+
const [ count ] = useGlobal('count');
748+
const add = useDispatch(
749+
(count, n) => count + n,
750+
'count',
751+
);
752+
return (
753+
<button onClick={() => add(1)}>
754+
{count}.
755+
</span>
756+
);
757+
}
758+
```
759+
760+
###### useDispatch(keyof Reducers)
761+
762+
`useDispatch('reducerName')` allows you to dispatch a global reducer.
763+
764+
```javascript
765+
import React, { useDispatch, useGlobal } from 'reactn';
766+
767+
function MyComponent() {
768+
const [ count ] = useGlobal('count');
769+
const add = useDispatch('add');
770+
return (
771+
<button onClick={() => add(1)}>
772+
{count}.
773+
</span>
774+
);
775+
}
776+
```
777+
778+
##### useGlobal
779+
780+
_Requires React >= 16.8.0_
781+
782+
`useGlobal` is a React Hook analogous to the `useState` Hook built into React
783+
itself. `useGlobal` returns the global state or parts thereof.
784+
785+
###### useGlobal()
786+
787+
`useGlobal()` with no parameters will return the entire global state object and
788+
a function for changing properties of the global state.
789+
790+
The `setGlobal` function returned by `useGlobal` is analogous to the
791+
[`setGlobal`](#setglobal) helper function and `this.setGlobal` class method.
792+
793+
```javascript
794+
import React, { useGlobal } from 'reactn';
795+
796+
function MyComponent() {
797+
const [ global, setGlobal ] = useGlobal();
798+
const generateNumber = () => {
799+
setGlobal(g => ({
800+
generations: g.generations + 1,
801+
myNumber: Math.floor(Math.random() * 100),
802+
});
803+
};
804+
return (
805+
<button onClick={generateNumber}>
806+
#{global.generations}: {global.myNumber}
807+
</button>
808+
);
809+
}
810+
```
811+
812+
###### useGlobal(keyof State)
813+
814+
`useGlobal('property')` returns a specific global state property and a function
815+
for updating that property.
816+
817+
```javascript
818+
import React, { useGlobal } from 'reactn';
819+
820+
const getRandomNumber = () =>
821+
Math.floor(Math.random() * 100);
822+
823+
function MyComponent() {
824+
const [ myNumber, setMyNumber ] = useGlobal('myNumber');
825+
return (
826+
<button onClick={() => setMyNumber(getRandomNumber())}>
827+
{myNumber}
828+
</button>
829+
)
830+
}
831+
```
832+
684833
##### withGlobal
685834
686835
Use `withGlobal` to return a higher-order component to convert global state
@@ -766,6 +915,133 @@ export default withInit(
766915
});
767916
```
768917
918+
## Terminology
919+
920+
ReactN strictly maintains accurate terminology for its data structures. The
921+
majority of ReactN's data structures are meant to be black box to simplify the
922+
user experience, only referenced by name in the package's code. They are
923+
outlined here for transparency and to ease community contributions.
924+
925+
### Dispatcher
926+
927+
When you pass a reducer to ReactN via [`addReducer`](#addreducer),
928+
[`addReducers`](#addreducers), [`useDispatch`](#usedispatch), or
929+
[`withInit`](#withinit), ReactN returns a dispatcher.
930+
931+
A dispatcher is a function that wraps a reducer, passing the global state and
932+
global reducers as parameters tying its return value to the global state.
933+
Dispatchers and reducers have a 1-to-1 relationship and are tightly bound to
934+
each other.
935+
936+
In documentation, dispatchers are often referred to as reducers to decrease the
937+
cognitive overhead and conceptually strengthen their 1-to-1 relationship.
938+
939+
For example, an "add" reducer may be defined as follows:
940+
941+
```javascript
942+
function add(global, _dispatch, n) {
943+
return { count: global.count + n };
944+
}
945+
```
946+
947+
When you call this reducer, you only need to call `add(1)`. This difference in
948+
call signature is because you are calling the _dispatcher_.
949+
950+
A dispatcher, in pseudo-code, conceptually looks as follows:
951+
952+
```javascript
953+
function dispatchAdd(n) {
954+
const { dispatchers, set, state } = globalStateManager;
955+
const newGlobalState = add(state, dispatchers, n);
956+
return set(newGlobalState);
957+
}
958+
```
959+
960+
### Global State Manager
961+
962+
The global state manager is the core object that powers ReactN. It maintains
963+
the state, global dispatchers, and subscriptions.
964+
965+
#### Default Global State Manager
966+
967+
The default global state manager is the global state manager used by all of
968+
ReactN _unless otherwise specified_. To specify a different global state
969+
manager, you must use a
970+
[Provider](https://github.com/CharlesStover/reactn/blob/master/Provider.md).
971+
972+
ReactN Components and Hooks will attempt to find a global state manager via
973+
the Context. If one does not exist via Context, it will fallback to the default
974+
global state manager.
975+
976+
### Reducer
977+
978+
A reducer is a function that accepts the current global state, a map of all
979+
global reducers, and any number of additional parameters. A reducer returns a
980+
change to the global state. It does not need to return the entire new global
981+
state. It only needs to return key-value pairs of changed properties.
982+
983+
An example "add" reducer may be defined as follows:
984+
985+
```javascript
986+
function add(global, _dispatch, n) {
987+
return { count: global.count + n };
988+
}
989+
```
990+
991+
A reducer may be asynchronous (return a Promise) and asynchronously dispatch
992+
other reducers. You can use a reducer that dispatches other reducers to create
993+
a "saga" of state changes.
994+
995+
```javascript
996+
async function mySaga(global, dispatch, shouldMultiply) {
997+
if (global.count < 0) {
998+
await dispatch.add(1);
999+
}
1000+
await dispatch.subtract(2);
1001+
if (shouldMultiply) {
1002+
await dispatch.multiply(3);
1003+
}
1004+
}
1005+
1006+
mySaga(true); // shouldMultiply = true
1007+
```
1008+
1009+
#### Property Reducer
1010+
1011+
A property reducer is a reducer that only changes one property. They only
1012+
receive that property's value as a parameter instead of the entire global state
1013+
object, and they do not receive the dispatch object as a parameter at all.
1014+
1015+
An example "add" property reducer may be defined as follows:
1016+
1017+
```javascript
1018+
function add(count, n) {
1019+
return count + n;
1020+
}
1021+
```
1022+
1023+
You must specify the property when _using_ a property reducer. Property
1024+
reducers cannot be added to or remembered by the global state manager.
1025+
1026+
```javascript
1027+
import React, { useDispatch, useGlobal } from 'reactn';
1028+
1029+
function add(count, n) {
1030+
return count + n;
1031+
}
1032+
1033+
function MyComponent() {
1034+
const [ count ] = useGlobal('count');
1035+
// Use the "add" property reducer on the "count" property.
1036+
const dispatch = useDispatch(add, 'count');
1037+
return (
1038+
<button onClick={() => dispatch(1)}>
1039+
{count}
1040+
</button>
1041+
)
1042+
}
1043+
```
1044+
7691045
## Support
7701046
7711047
For support, reach out to us on the

jest.config.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module.exports = {
22
cacheDirectory: './jest/cache',
3-
collectCoverage: true,
3+
collectCoverage: false,
44
collectCoverageFrom: [
55
'src/**/*',
66
],
@@ -10,6 +10,10 @@ module.exports = {
1010
resetModules: true,
1111
restoreMocks: true,
1212
roots: [ "<rootDir>/tests" ],
13+
setupFilesAfterEnv: [
14+
'@testing-library/jest-dom/extend-expect',
15+
'@testing-library/react/cleanup-after-each',
16+
],
1317
testRegex: '/tests/.+\\.test\\.tsx?$',
1418
verbose: false,
1519
};

package.json

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "reactn",
3-
"version": "2.1.5",
3+
"version": "2.1.6",
44
"author": "Charles Stover <[email protected]>",
55
"description": "React, but with built-in global state management.",
66
"homepage": "https://github.com/CharlesStover/reactn#readme",
@@ -35,6 +35,8 @@
3535
"@babel/core": "^7.4.0",
3636
"@babel/preset-env": "^7.4.2",
3737
"@babel/preset-typescript": "^7.3.3",
38+
"@testing-library/jest-dom": "^4.0.0",
39+
"@testing-library/react": "^8.0.5",
3840
"@types/jest": "^24.0.11",
3941
"@types/node": "^12.6.2",
4042
"@types/react": "^16.7.13",
@@ -46,14 +48,13 @@
4648
"jest": "^24.6.0",
4749
"react": "^16.8.6",
4850
"react-dom": "^16.8.6",
49-
"react-testing-library": "^6.0.4",
5051
"ts-jest": "^24.0.1",
5152
"ts-node": "^8.0.2",
5253
"typescript": "^3.3.1"
5354
},
5455
"peerDependencies": {
5556
"@types/react": "^16.8.0",
56-
"react": "^16.3.0",
57-
"react-dom": "^16.3.0"
57+
"react": "*",
58+
"react-dom": "*"
5859
}
5960
}

0 commit comments

Comments
 (0)