Skip to content

Commit

Permalink
useResetReducer bugfix and format for minification
Browse files Browse the repository at this point in the history
  • Loading branch information
patrickroberts committed Feb 13, 2021
1 parent f1e610c commit 420d979
Show file tree
Hide file tree
Showing 13 changed files with 55 additions and 69 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "suspense-service",
"version": "0.2.7",
"version": "0.2.8",
"description": "Suspense integration library for React",
"repository": "github:patrickroberts/suspense-service",
"main": "dst/cjs/suspense-service.js",
Expand Down
16 changes: 8 additions & 8 deletions src/IdContext/Consumer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ export function createIdContextConsumer<T>(
{ Consumer }: Context<Environment<T>>,
): IdContextConsumer<T> {
const EnvironmentConsumer: IdContextConsumer<T> = ({ id, children }) => {
const render = useCallback((env: Environment<T>) => {
const value = unwrap(env, id);
const render = useCallback(
(env: Environment<T>) => children(unwrap(env, id)),
[id, children],
);

return children(value);
}, [id, children]);

return useMemo(() => (
<Consumer>{render}</Consumer>
), [render]);
return useMemo(
() => <Consumer>{render}</Consumer>,
[render],
);
};

EnvironmentConsumer.defaultProps = defaultProps;
Expand Down
17 changes: 5 additions & 12 deletions src/IdContext/Environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,18 @@ import Id from './Id';

/** @internal */
export default interface Environment<T> {
has (key: Id): boolean;
get (key: Id): T | undefined;
[Symbol.iterator] (): IterableIterator<[Id, T]>;
has(key: Id): boolean;
get(key: Id): T | undefined;
[Symbol.iterator](): IterableIterator<[Id, T]>;
}

/** @ignore */
export function wrap<T>(
env: Environment<T>,
value: T,
id: Id = null,
): Environment<T> {
export function wrap<T>(env: Environment<T>, value: T, id: Id = null): Environment<T> {
return new Map(env).set(id, value).set(null, value);
}

/** @ignore */
export function unwrap<T>(
env: Environment<T>,
id: Id = null,
): T {
export function unwrap<T>(env: Environment<T>, id: Id = null): T {
if (!env.has(id)) {
throw new Error(`Provider with id ${String(id)} is not in scope`);
}
Expand Down
14 changes: 8 additions & 6 deletions src/IdContext/Provider/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@ export function createIdContextProvider<T>(
const { Provider } = EnvironmentContext;
const EnvironmentProvider: IdContextProvider<T> = ({ value, id, children }) => {
const prev = useContext(EnvironmentContext);
const next = useMemo(() => (
wrap(prev, value, id)
), [value, id, prev]);
const next = useMemo(
() => wrap(prev, value, id),
[value, id, prev],
);

return useMemo(() => (
<Provider value={next}>{children}</Provider>
), [children, next]);
return useMemo(
() => <Provider value={next}>{children}</Provider>,
[children, next],
);
};

EnvironmentProvider.defaultProps = defaultProps;
Expand Down
16 changes: 6 additions & 10 deletions src/Service/Consumer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,13 @@ export function createServiceConsumer<TRequest, TResponse>(
const ResourceConsumer: ServiceConsumer<TRequest, TResponse> = ({ id, children }) => {
const render = useCallback((
resourceAndSetState: [Resource<TResponse>, Dispatch<SetStateAction<TRequest>>],
) => {
const resource = resourceAndSetState[0];
const setState = resourceAndSetState[1];
const response = resource();
) => children(resourceAndSetState[0](), resourceAndSetState[1]),
[children]);

return children(response, setState);
}, [children]);

return useMemo(() => (
<Consumer id={id}>{render}</Consumer>
), [id, render]);
return useMemo(
() => <Consumer id={id}>{render}</Consumer>,
[id, render],
);
};

ResourceConsumer.defaultProps = defaultProps;
Expand Down
5 changes: 1 addition & 4 deletions src/Service/Handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,10 @@ export function createUseHandler<TRequest, TResponse>(

state = { promise, status: Status.Pending };
return () => {
const { status } = state;

switch (state.status) {
case Status.Pending: throw state.promise;
case Status.Fulfilled: return state.value;
case Status.Rejected: throw state.reason;
default: throw new Error(`Unexpected status ${status}`);
default: throw state.reason;
}
};
}, [request, id]);
Expand Down
19 changes: 9 additions & 10 deletions src/Service/Provider/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,17 @@ export function createServiceProvider<TRequest, TResponse>(
request, id, children, fallback, reset,
}) => {
const stateAndSetState = useResetState(request, reset);
const state = stateAndSetState[0];
const resource = useHandler(stateAndSetState[0], id);
const setState = stateAndSetState[1];
const resource = useHandler(state, id);
const element = useMemo(() => (
fallback != null
? <Suspense fallback={fallback}>{children}</Suspense>
: children
), [children, fallback]);
const element = useMemo(
() => (fallback == null ? children : <Suspense fallback={fallback}>{children}</Suspense>),
[children, fallback],
);

return useMemo(() => (
<Provider value={[resource, setState]} id={id}>{element}</Provider>
), [resource, setState, id, element]);
return useMemo(
() => <Provider value={[resource, setState]} id={id}>{element}</Provider>,
[resource, setState, id, element],
);
};

ResourceProvider.defaultProps = defaultProps;
Expand Down
2 changes: 1 addition & 1 deletion src/Service/Status.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
const enum Status {
Pending,
Fulfilled,
Rejected
Rejected,
}

export default Status;
7 changes: 2 additions & 5 deletions src/Service/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export function createService<TRequest, TResponse>(
handler: Handler<TRequest, TResponse>,
): Service<TRequest, TResponse> {
const ResourceContext = createIdContext<[
Resource<TResponse>, Dispatch<SetStateAction<TRequest>>
Resource<TResponse>, Dispatch<SetStateAction<TRequest>>,
]>(defaultValue);

return {
Expand All @@ -54,11 +54,8 @@ export function useServiceState<TRequest, TResponse>(
service: Service<TRequest, TResponse>, id: Id = null,
): [TResponse, Dispatch<SetStateAction<TRequest>>] {
const resourceAndSetState = useIdContext(service[kResource], id);
const resource = resourceAndSetState[0];
const setState = resourceAndSetState[1];
const response = resource();

return [response, setState];
return [resourceAndSetState[0](), resourceAndSetState[1]];
}

/**
Expand Down
8 changes: 6 additions & 2 deletions src/State/useResetReducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,12 @@ export default function useResetReducer<R extends Reducer<any, any>>(
initialState,
state: initialState,
dispatch: (action: ReducerAction<R>) => {
current.state = current.reducer(current.state, action);
forceUpdate();
const nextState = current.reducer(current.state, action);

if (!Object.is(current.state, nextState)) {
current.state = nextState;
forceUpdate();
}
},
});

Expand Down
7 changes: 1 addition & 6 deletions src/StateContext/Consumer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,7 @@ export function createStateContextConsumer<T>(
): StateContextConsumer<T> {
const StateConsumer: StateContextConsumer<T> = ({ id, children }) => {
const render = useCallback(
(stateAndSetState: State<T>) => {
const state = stateAndSetState[0];
const setState = stateAndSetState[1];

return children(state, setState);
},
(stateAndSetState: State<T>) => children(stateAndSetState[0], stateAndSetState[1]),
[children],
);

Expand Down
7 changes: 4 additions & 3 deletions src/StateContext/Provider/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ export function createStateContextProvider<T>(
const StateProvider: StateContextProvider<T> = ({ value, id, children, reset }) => {
const state = useResetState(value, reset);

return useMemo(() => (
<Provider value={state} id={id}>{children}</Provider>
), [state, id, children]);
return useMemo(
() => <Provider value={state} id={id}>{children}</Provider>,
[state, id, children],
);
};

StateProvider.defaultProps = defaultProps;
Expand Down
4 changes: 3 additions & 1 deletion src/StateContext/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,16 @@ export default interface StateContext<T> {
[kState]: IdContext<State<T>>;
}

const defaultDispatch = () => undefined;

/**
* Creates a State Context for providing a stateful value and a function to update it.
* @param defaultValue the value consumed if no {@link StateContextProvider} is in scope and the
* {@link StateContextConsumerProps.id | consumer `id`} is `null`
*/
export function createStateContext<T>(defaultValue: T): StateContext<T> {
const StateContext = createIdContext<State<T>>(
[defaultValue, () => undefined],
[defaultValue, defaultDispatch],
);

return {
Expand Down

0 comments on commit 420d979

Please sign in to comment.