Skip to content

Instantly share code, notes, and snippets.

@joliveros
Last active January 13, 2020 20:12
Show Gist options
  • Save joliveros/d3d9324f446178f280e4b72190196d11 to your computer and use it in GitHub Desktop.
Save joliveros/d3d9324f446178f280e4b72190196d11 to your computer and use it in GitHub Desktop.

Source/Author

https://github.com/bexic/react-without-redux

Global Store

import React, {
	createContext,
	useContext,
	useReducer,
	useCallback
} from 'react';

import { IContextProps } from 'common/types';

import { asyncer } from 'store/middlewares';
import mainReducer, { initialState } from 'store/reducers';

const GlobalStore = createContext({} as IContextProps);

export const useGlobalStore = () => useContext(GlobalStore);

export default function Provider({ children } : { children: React.ReactNode}) {
	const [ state, dispatchBase ] = useReducer(mainReducer, initialState);

	const dispatch = useCallback(asyncer(dispatchBase, state), []);

	return (
		<GlobalStore.Provider value={{ state, dispatch }}>
			{children}
		</GlobalStore.Provider>
	);
}

Reducer

export default function mainReducer(state: IState, action: object) {
	// Receiving previous state here
	const { items, login } = state;

	// Receiving current state here
	const currentState = {
		items: itemsReducer.reducer(items, action),
		login: loginReducer.reducer(login, action)
	};

	// Middlewares
	logger(action, state, currentState);

	return currentState;
}

Actions

	const dispatch = useCallback(asyncer(dispatchBase, state), []);

	return (
		<GlobalStore.Provider value={{ state, dispatch }}>
			{children}
		</GlobalStore.Provider>
	);

Sync/Async

export function handleFetch() {
  return async function (dispatch) {
    try {
      const data = await fetchItems()
      // async
      dispatch(setItems(data))
    } catch (err) {
      // sync
      dispatch(error(err))
    }
  }
}

Replace Higher-Order Components with Hooks!

Custom Hook

const useItems: any = () => {
	const { state , dispatch } = useGlobalStore();

	// List of Props
	const { items } = state;

	// List of Actions
	const {
		addItem,
		resetItems,
		completeItem
	} = actions;

	// Bind Actions
	const itemsActions = bindActions({
		addItem,
		resetItems,
		completeItem
	}, dispatch);

	return { items, ...itemsActions };
}

Use the Hook!

const TodoItem: React.FC<TodoItemProps> = props => {
	const { completeItem } = useItems();

	const handleComplete = () => {
		completeItem(props.id);
	}

	return (
		<div className='todo-item'>
			<input
				id={props.id.toString()}
				type='checkbox'
				checked={props.completed}
				onChange={handleComplete} />
			<label htmlFor={props.id.toString()} className={'todo-item-text' + (props.completed ? ' completed' : '')}>{props.text}</label>
		</div>
	);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment