【问题标题】:Communicating between siblings in React在 React 中的兄弟姐妹之间进行通信
【发布时间】:2020-10-04 12:28:57
【问题描述】:

我正在用 Typescript/React 编写一个 CPU 模拟器。我有一个CodeExecutionViewCPUTerminal

现在,当CPU 触发适当的指令时,我想将一些数据写入Terminal。我要写入的数据位于CPUstate。我用来向终端写入数据的函数位于TerminalView 组件中。如何传递该函数以供 CPU 类使用?

我的代码结构如下所示:

                   ___________
                  |           |
                  | MAIN VIEW |
                  |(component)|
                  |___________|
          ___________      ___________
         |           |    |           |
         |    CPU    |    | TERMINAL  |
         |  (class)  |    |(component)|
         |___________|    |___________|

主要组件:

type ExecutionState = {
    assemblerOutput: Array<{ line: ParsedLine; bytes: Array<HexNum> }>;
    currentInstruction: Instruction;
    currentPC: number;
    currentInstructionLength: number;
    cpuState: CPUState;
}

type ExecutionProps = {
    assemblerOutput: Array<{ line: ParsedLine; bytes: Array<HexNum> }>;
}

export default class ExecutionScreen extends React.Component<ExecutionProps, ExecutionState> {
    state: ExecutionState = {
        assemblerOutput: [],
        currentInstruction: undefined,
        currentPC: 0,
        currentInstructionLength: 0,
        cpuState: undefined
    }

    private CPU: CPU;

    constructor(props: ExecutionProps) {
        super(props);
        this.CPU = new CPU(props.assemblerOutput);
        this.state = {
            assemblerOutput: props.assemblerOutput,
            currentInstruction: this.CPU.currentInstruction,
            currentPC: this.CPU.prevPC,
            currentInstructionLength: undefined,
            cpuState: this.CPU.getFullState()
        };
    }

    runNextInstruction(): void {
        this.CPU.executeInstruction();
        this.setState({ ...this.state, currentInstruction: this.CPU.currentInstruction, currentInstructionLength: this.CPU.currentInstruction.size, currentPC: this.CPU.prevPC, cpuState: this.CPU.getFullState() });
    }

    render(): ReactElement {
        return (
            <>
                <Button key={0} onClick={ this.runNextInstruction.bind(this) }>Next</Button>
                <TerminalView />
            </>
        );
    }
}

终端组件:

export default class TerminalView extends React.Component {
    private readonly terminalRef: React.RefObject<XTerm>;
    private terminal: Terminal;

    constructor(props: ReactPropTypes) {
        super(props);
        this.terminalRef = React.createRef();
    }

    componentDidMount(): void {
        this.terminal = this.terminalRef.current.getTerminal();
        this.handleTerminal();
        this.writeHexNum([new HexNum(66), new HexNum(10), new HexNum(66)]);
    }

    render(): React.ReactElement {
        return (
            <>
                <XTerm
                    ref={this.terminalRef}
                />
            </>
        );
    }

    // the function i want to be accesible to the CPU
    // the most important one would be terminal.write()
    writeHexNum(values: Array<HexNum>): void {
        this.terminal.write(values.map(value => value.toAscii()).join(""));
    }
}

我不希望更改代码的结构,因为我需要 CPU 类存在于主视图中,以便其他事情正常工作

【问题讨论】:

  • 在 TerminalView 的 props 中添加你的 CP 类,在 CP 的构造函数中添加 TerminalView

标签: javascript node.js reactjs typescript


【解决方案1】:

react 中的兄弟姐妹不直接通信,而是需要通过共享父节点进行通信,该父节点持有共享状态。您可以在主视图状态下定义一个数组来保存终端线。然后 CPU 可以推送到该阵列。在下面的代码中,我将此变量命名为terminalLines

type ExecutionState = {
    assemblerOutput: Array<{ line: ParsedLine; bytes: Array<HexNum> }>;
    currentInstruction: Instruction;
    currentPC: number;
    currentInstructionLength: number;
    cpuState: CPUState;
    terminalLines: string[]
}

然后给终端添加一个属性,绑定到数组中。

    render(): ReactElement {
        return (
            <>
                <Button key={0} onClick={ this.runNextInstruction.bind(this) }>Next</Button>
                <TerminalView lines={ this.terminalLines } />
            </>
        );
    }

您需要为终端上的道具定义一个类,然后将渲染修改为类似于。

    render(props: Props): React.ReactElement {
        this.terminal.write(props.lines.map(value => value.toAscii()).join(""));
        return (
            <>
                <XTerm
                    ref={this.terminalRef}
                />
            </>
        );
    }

我还没有机会测试这段代码。您可能需要添加逻辑以保持数组变得过大,例如保持最后几百行。

【讨论】:

  • 这确实是个好办法。我最终决定让 CPU 成为主要组件,但我可以确认这种方法有效
猜你喜欢
  • 2019-05-06
  • 2017-04-23
  • 2018-02-04
  • 2020-01-31
  • 2023-03-03
  • 2015-03-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多