#Day77 of #100daysofcode
Thank you Captain @Stennie_X .
As we saw in the State Reducer pattern that we can provide custom reducers to our hook and that will in return update our state accordingly, but what if we want to give this state control to a component that can mutate the state of this component(hook) from outside.
So, here we are with our Control Props React Pattern implementation, that’s exactly applicable in the above said situations.
function useToggle({
initialOn = false,
reducer = toggleReducer,
on: controlledOn,
onChange,
} = {}) {
const {current: initialState} = React.useRef({on: initialOn})
const [state, dispatch] = React.useReducer(reducer, initialState)
const onIsControlled = controlledOn != null
const on = onIsControlled ? controlledOn : state.on
const dispatchWithOnChange = action => {
if (!onIsControlled) {
dispatch(action)
}
onChange(reducer({...state, on}, action), action)
}
const toggle = () => dispatchWithOnChange({type: actionTypes.toggle})
const reset = () => dispatchWithOnChange({type: actionTypes.reset, initialState})
... some prop collection implementation here...
return {
on,
reset,
toggle,
getTogglerProps,
getResetterProps,
}
}
function Toggle({on: controlledOn, onChange}) {
const {on, getTogglerProps} = useToggle({on: controlledOn, onChange})
const props = getTogglerProps({on})
return <Switch {...props} />
}
function App() {
const [bothOn, setBothOn] = React.useState(false)
const [timesClicked, setTimesClicked] = React.useState(0)
function handleToggleChange(state, action) {
if (action.type === actionTypes.toggle && timesClicked > 4) {
return
}
setBothOn(state.on)
setTimesClicked(c => c + 1)
}
function handleResetClick() {
setBothOn(false)
setTimesClicked(0)
}
return (
<div>
<Toggle on={bothOn} onChange={handleToggleChange} />
<Toggle on={bothOn} onChange={handleToggleChange} />
.... some more JSX here ...
</div>
)
}
In the above implementation, we are making both the <Toggle/>
components synchronized.