Tengo un grupo de componentes nativos de reacción que tienen interfaces similares. El método importante en la interfaz es el método de ejecución. Los usuarios pueden ejecutar este método de ejecución presionando un botón de acción para cada uno de los componentes o presionando un botón de acción en el nivel principal, que iterará a través de cada uno de estos componentes similares usando su referencia y llamando al método de ejecución. Aquí hay una versión simplificada de la configuración.
const Test1 = forwardRef((props, ref) => { const [importantState, setimportantState] = useState('initial') useImperativeHandle(ref, () => ({ run: run, })) const run = async () => { // This function will open a modal // where users will eventually change the important state openInteractionModal() // The idea of this promiss is to settle when the users // eventually change the importantState thorugh thier interaction // It does so by checking the state every 100 miliseconds // This however is a problem as a result of the setInterval function will // inclose the initial state instead of getting the new value each time return new Promise((resolve, reject) => { let interval = setInterval(() => { if (importantStat === 'complete') { resolve('success') clearInterval(interval) } else if (importantStat === 'failed') { reject('failed') clearInterval(interval) } }, 100) }) } return ( <> <Button title="run" onPress={run} /> </> ) }) const parentComponent = () => { const test1Ref = userRef(null) const test2Ref = userRef(null) const test3Ref = userRef(null) const testRefs = [test1Ref, test2Ref, test3Ref] const autoRun = async () => { testRefs.forEach(ref => { await ref?.current.run() }); } return ( <> <Button title="Auto run" onPress={autoRun} /> <Test1 ref={test1Ref} />, <Test2 ref={test2Ref} />, <Test3 ref={test3Ref} />, </> ) }El problema que tengo en este momento es que la promesa que devuelvo de estos componentes individuales nunca se cumple como resultado del cierre que mencioné anteriormente en los comentarios. ¿Hay alguna manera de superar este cierre, o hay un mejor patrón nativo de reacción que estoy usando ahora mismo?
No vayas a votar. En su lugar, pase la función de resolve como argumento a openInteractionModal y llámela junto con setImportantState desde el cuadro de diálogo modal.
Si eso no es posible por alguna razón, puede usar una referencia para almacenar la función de resolve y ejecutarla desde un efecto cuando cambia el estado:
const onImportantStateChange = useRef(); useEffect(() => { if (!onImportantStateChange.current) return; if (importantState === 'complete') { onImportantStateChange.current('success'); onImportantStateChange.current = undefined; } else if (importantState === 'failed') { onImportantStateChange.current(Promise.reject(new Error('failure'))); onImportantStateChange.current = undefined; } }, [importantState]) const run = async () => { return new Promise(resolve => { onImportantStateChange.current = resolve; // This function will open a modal // where users will eventually change the important state openInteractionModal(); }); }Cree una referencia y almacene el estado en eso en lugar del estado del componente Test1.
Como eso
const importantState = useRef(null);Establecer valor en la corriente de la ref.
importantState.current="complete"Más tarde, utilícelo en setInterval como
if(importantState.current === "complete")