Skip to content

Instantly share code, notes, and snippets.

@compulim
Created January 26, 2020 00:31
Show Gist options
  • Save compulim/51676ea9798a5156db8beb3c97edd8a6 to your computer and use it in GitHub Desktop.
Save compulim/51676ea9798a5156db8beb3c97edd8a6 to your computer and use it in GitHub Desktop.
useReducerWithSaga
import { useCallback } from 'react';
import useReducerWithSaga from './useReducerWithSaga';
import saga from '../data/saga';
const DEFAULT_STATE = {
localStream: null,
remoteStreams: []
};
function reducer(state, action) {
switch (action.type) {
case 'CONNECT_FULFILLED':
state = { ...state, connected: true };
break;
case 'DISCONNECT':
state = { ...state, connected: false };
break;
case 'SET_LOCAL_STREAM':
state = { ...state, localStream: action.payload.stream };
break;
case 'ADD_REMOTE_STREAMS':
state = { ...state, remoteStreams: [...state.remoteStreams, ...action.payload.streams] };
break;
default:
break;
}
return state;
}
export default function useApp2() {
const [state, dispatch] = useReducerWithSaga(reducer, DEFAULT_STATE, saga);
const handleConnectClick = useCallback(() => dispatch({ type: 'CONNECT' }), [dispatch]);
const handleDisconnectClick = useCallback(() => dispatch({ type: 'DISCONNECT' }), [dispatch]);
return [
{
localStream: state.localStream,
readyState: state.connected ? 'connected' : 'idle',
remoteStreams: state.remoteStreams
},
{
handleConnectClick,
handleDisconnectClick
}
];
}
import { useCallback, useEffect, useMemo, useReducer, useRef } from 'react';
import { eventChannel, runSaga, END } from 'redux-saga';
export default function useReducerSaga(reducer, initialState, saga) {
const [state, dispatch] = useReducer(reducer, initialState);
const getStateRef = useRef(() => state);
const sagaEmitterRef = useRef();
const channel = useMemo(
() =>
eventChannel(emitter => {
sagaEmitterRef.current = emitter;
return () => {
sagaEmitterRef.current = null;
};
}),
[]
);
useEffect(() => {
const task = runSaga({ channel, dispatch, getState: getStateRef.current }, saga);
return () => {
sagaEmitterRef.current(END);
task.end();
};
}, [channel, saga]);
const dispatchWithSaga = useCallback(
action => {
dispatch(action);
sagaEmitterRef.current(action);
},
[]
);
return [state, dispatchWithSaga];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment