algunos problemas con el estado en TypeScript React.
Un componente secundario pasa un objeto 'terminal' al principal a través de una función pasada llamada returnTerminal() . Este objeto terminal luego se almacena como un _object . useEffect() dice que _object no es nulo eventualmente, pero callback() mantiene continuamente que _object es nulo, y no estoy seguro de por qué.
Componente principal
const Parent: React.FunctionComponent<ParentProps> = () => { const [_object, set_object] = useState<Terminal>(null); const handleGetTerminal = (terminal: Terminal) => { set_object(terminal); }; useEffect(() => { if (_object !== null) { _object.writeln("_object is not null"); // This prints just fine } }, [_object]); return ( <Child returnTerminal={(term) => handleGetTerminal(term)} callback={() => { console.log(_object === null); // This returns true - the object is null for some reason??? }} /> ); };Componente hijo
const Child: React.FunctionComponent<ChildProps> = (props) => { const { callback, returnTerminal } = props; // The ref where the terminal will be stored and returned const ref = useRef<HTMLDivElement>(null); // The xterm.js terminal object const terminal = new Terminal(); useLayoutEffect(() => { // Calls whenever terminal is typed into if (callback) terminal.onData(callback); // Mount terminal to the DOM if (ref.current) terminal.open(ref.current); // Pass the terminal to the parent object returnTerminal(terminal); }, []); return <div ref={ref}></div>; }; export default Child; La callback() siempre devuelve que _object es nulo, sin importar cuánto tiempo espere.
La respuesta terminó siendo el uso de useImperativeHandle y forwardRef. Aquí está el código completo.
Padre
import Child from "./child"; interface ParentProps { name?: string; } const Parent: React.FunctionComponent<ParentProps> = () => { type ChildHandle = ElementRef<typeof Child>; const childRef = useRef<Child>(null); let _object: Terminal; // same Terminal type that Child uses useEffect(() => { if (childRef.current) { _object = childRef.current.get(); // imperitive handle function _object.writeln(“_object loaded”); } }, []); return ( <Child ref={childRef} callback={() => { terminal.writeln("_object is not null”); // THIS finally works }} /> ); };Niño
interface ChildProps { callback?(data: string): void; } type ChildHandle = { get: () => Terminal; }; const Child: ForwardRefRenderFunction<ChildHandle, ChildProps> = ( props, forRef ) => { const { callback } = props; const terminal = new Terminal(); // The ref where the terminal will be stored and returned const ref = useRef<HTMLDivElement>(null); useImperativeHandle(forRef, () => ({ get() { return terminal; }, })); useLayoutEffect(() => { // Calls whenever terminal is typed into if (callback) terminal.onData(callback); // Mount terminal to the DOM if (ref.current) terminal.open(ref.current); }, []); return <div ref={ref}></div>; }; export default forwardRef(Child);