Tengo este componente que usa useState y envuelve a sus elementos secundarios en un componente Modal , que es un componente antiguo de nuestra aplicación, y el componente modal resulta ser una pesadilla total. Pero se necesita un objeto acceptData que tiene un accesorio de callback de llamada para cuando se hace clic en el botón "aceptar".
Mi problema es que mi componente está actualizando su estado a través de otro elemento secundario (consulte onFileReadComplete ), pero luego, cuando se hace clic en el botón, ese estado es nulo. Incluso puedo ver en las herramientas de desarrollo de React que el estado no es nulo, tiene el valor que espero.
Aquí está el componente:
const CSVEditSwitcher = ({ acceptData, hideData }) => { const [parsedData, setParsedData] = useState(null); const dispatch = useDispatch(); const enterLineups = lineupObject => dispatch(csvEditAPI(lineupObject)); const modalProps = { className: "csv-upload", commonHide: true, acceptData: { actionName: "Submit", className: acceptData.className, callback: () => { if (!parsedData) { console.log("no data!"); // we keep getting here! return; } enterLineups(parsedData.masterLineups).then(acceptData.callback); }, }, hideData, validator: () => true, }; return ( <Modal {...modalProps}> {!parsedData ? ( <UploadEditTemplate onFileReadComplete={data => { console.log({ data }); // this is always correct! setParsedData(data); }} /> ) : ( <ImportResults {...parsedData} /> )} </Modal> ); }; En caso de que this problema sea un poco loco, he intentado reemplazar la devolución de llamada con una sintaxis de function () { } , sin éxito.
No hay nada interesante en el punto de llamada para la devolución de llamada en Modal :
accept(e) { if (!e) return; if (e.key && (e.key !== "Enter" || e.key !== "Return")) return; const { acceptCallback } = this.state; console.log(acceptCallback, e); if (acceptCallback) acceptCallback(e); } Como avemaría, intenté convertir esto en un componente de clase (envolviéndolo en un componente funcional que proporciona los valores de enlace). En realidad funciona, pero solo cuando se accede a this.state.parsedData explícitamente en la devolución de llamada. es decir, tengo const { parsedData } = this.state en la parte superior del método de render para los otros usos de ese valor, pero la variable desestructurada no funciona en la devolución de llamada.
¡Me encantaría que alguien pudiera darme una idea de qué diablos está pasando aquí!
Al desestructurar accesorios en inyección ( {...modalProps} ...), crea una nueva instancia en la memoria. Por lo tanto, la función de callback de llamada siempre tendrá un valor parsedData inicial.
Mi sugerencia es usar la callback de llamada como referencia para usar la useCallback de llamada que es consciente de la manipulación del estado.
const callback = useCallback(() => { if (!parsedData) { console.log("no data!") return; } enterLineups(parsedData.masterLineups).then(acceptData.callback); }, [parsedData]) const modalProps = { className: "csv-upload", commonHide: true, acceptData: { actionName: "Submit", className: acceptData.className, callback }, hideData, validator: () => true, };