Представим что у нас есть приложение вида:
<App>
<Widget />
</App>
Где <Widget />
это компонент имеющий своё внутренее состояние которое мы хотим сбросить.
const [widgetReset, setWidgetReset] = useState(false);
// some if
setWidgetReset(true);
return <Widget isReset={widgetReset} />
Однако чтобы это работало более одного раза нам надо или сделать хитрую функцию установки значения:
const [triggerReset, setTriggerReset] = useState();
const resetWidget = useCallback(
() => setTriggerReset(Performance.now()),
[setTriggerReset]
);
// some if
resetWidget();
return <Widget triggerReset={triggerReset} />
Или добавить пропс onReset для возврата в исходное состояние:
const [widgetReset, setWidgetReset] = useState(false);
const onReset = useCallback(
() => setWidgetReset(false),
[setWidgetReset]
);
// some if
setWidgetReset(false)
return <Widget isReset={widgetReset} onReset={onReset}/>
const resetWidgetRef = useRef();
const resetWidget = useCallback(
() => typeof resetWidgetRef.current === 'function' && resetWidgetRef.current(),
[resetWidgetRef]
);
// some if
resetWidget()
return (
<Widget>
{ (reset) => resetWidgetRef.current = reset }
</Widget>
)
В этом случае сперва нужно сделать forwardRef
обертку над Widget компонентом
function Widget(props, ref) {
const [state, setState] = useState(initialState);
useImperativeHandle(ref, () => ({
reset: () => setState(initialState)
}));
return <div>{ /* some JSX */ }</div>;
}
const ForwardedWidget = forwardRef(FancyInput);
export ForwardedWidget;
Далее используем как:
const widgetRef = useRef();
const resetWidget = useCallback(
() => typeof widgetRef.current?.reset === 'function' && widgetRef.current.reset(),
[resetWidgetRef]
);
// some if
resetWidget()
return (
<Widget ref={widgetRef} />
)
Если нужно сбросить состояние дочернего компонента - дестрою старый, создаю новый (в React установить новый 'key', angular немного танцев с "trackBy")