You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Golden Layout动态标签页点击后数据不更新问题求助

Fixing Golden Layout + React Issues: Duplicate Button Clicks & Tab Loading Errors

Let's break down the problems in your code and fix them step by step. I've identified several key issues that are causing your second "View" button to fail and tab loading errors:

1. Duplicate Component Registration (Major Error Source)

You're calling myLayout.registerComponent() every time the "View" button is clicked. Golden Layout throws an error when you try to register a component that's already registered, which is why your tab loading fails after the first click.

Fix: Move component registration to the componentDidMount lifecycle method so it only runs once when the Applications component initializes.

2. Unreliable Global State (global.sendId)

Using a global variable to pass the selected ID is bad practice in React—it makes state tracking unpredictable and can cause race conditions when clicking multiple buttons.

Fix: Use Golden Layout's event hub or component props to pass data, and rely on React's local state instead of global variables.

3. Flawed Child Component Count Check

Your condition myLayout.root.contentItems[0].contentItems.length-1 >1 is incorrect. It's checking if the number of child items minus one is greater than 1, which doesn't properly detect if the tabs already exist. This leads to either duplicate tabs or failing to update existing ones.

Fix: Check if the target components already exist in the layout. If they do, update their props with the new ID instead of creating new ones. If not, add them as new children.

4. Stale Props in Child Components

Once you add a component to Golden Layout, it doesn't automatically update its props when you click a new "View" button. You need to explicitly send the new data to the existing component instances.

Fix: Use Golden Layout's event hub to emit an event with the new ID, and have child components listen for this event to update their state.

5. Syntax Error in render Method

You have a typo: let value = this.pro should be let value = this.props.data—this is causing an unexpected error that might be blocking other logic.


Modified Code Examples

Updated Applications.js

import React, { Component } from 'react';
import data from '../common'
import titlesparcels from './titlesparcels';
import Services from './Services';
import Document from './document';

class Applications extends Component {
  constructor(props){
    super(props);
    this.state = { userData: '' };
    this.myLayout = null;
  }

  componentDidMount() {
    // Register components ONCE when the component mounts
    this.myLayout = this.props.glEventHub._layoutManager;
    this.myLayout.registerComponent('titlesparcels', titlesparcels);
    this.myLayout.registerComponent('Services', Services);
    this.myLayout.registerComponent('Document', Document);
  }

  renderHeader(){
    return(
      <div>
        <table style={{width: '100em'}} className="table table-striped">
          <thead>
            <tr>
              <th>Application Id</th>
              <th>agent</th>
              <th>status</th>
              <th>partyType</th>
              <th>lodgedDate</th>
              <th>View</th>
            </tr>
          </thead>
        </table>
      </div>
    )
  }

  renderData(){
    return data.applications.map((val,key)=>{
      return(
        <div key={val.id}>
          <table className="table table-striped">
            <tbody>
              <tr>
                <td>{val.general.applicationId}</td>
                <td>{val.general.agent}</td>
                <td>{val.general.status}</td>
                <td>{val.general.partyType}</td>
                <td>{val.general.lodgedDate}</td>
                <td><button onClick={()=> this.showTble(val.id)} >View</button></td>
              </tr>
            </tbody>
          </table>
        </div>
      );
    });
  }

  showTble=(id)=> {
    this.setState({ userData: id });
    const layoutRoot = this.myLayout.root.contentItems[0];

    // Check if child components already exist
    const titlesParcelsComp = layoutRoot.contentItems.find(item => item.config.title === 'Titles & Parcels');
    const servicesComp = layoutRoot.contentItems.find(item => item.config.title === 'Services');
    const documentContainer = layoutRoot.contentItems.find(item => item.config.title === 'Documents');

    if (titlesParcelsComp && servicesComp) {
      // Update existing components with new ID via event hub
      this.myLayout.eventHub.emit('update-data', { id });
    } else {
      // Add new components if they don't exist
      const titleparcelsConfig = {
        title: 'Titles & Parcels',
        type: 'react-component',
        component: 'titlesparcels',
        isClosable: false,
        props: { id }
      };
      const servicesConfig = {
        title: 'Services',
        type: 'react-component',
        component: 'Services',
        isClosable: false,
        props: { id }
      };

      layoutRoot.addChild(titleparcelsConfig);
      layoutRoot.addChild(servicesConfig);

      // Add Documents tab and its children
      let documentWindowAdded = false;
      data.applications.forEach(val => {
        if(val.id === id){
          val.documents.forEach(element => {
            const documentConfig = {
              title: element.source, // Use document name as title
              type: 'react-component',
              component: 'Document',
              isClosable: false,
              props: { doc: element.source }
            };

            if(!documentWindowAdded){
              // Create main Documents container first
              const mainDocumentConfig = {
                title: 'Documents',
                type: 'column', // Use column to stack documents vertically
                isClosable: false
              };
              const docContainer = layoutRoot.addChild(mainDocumentConfig);
              docContainer.addChild(documentConfig);
              documentWindowAdded = true;
            } else {
              // Add to existing Documents container
              documentContainer.addChild(documentConfig);
            }
          });
        }
      });
    }
  }

  render() {
    // Fix typo here
    if(this.props.data){
      let value = this.props.data;
      console.log("value from userData", value);
    }
    return(
      <div>
        {this.renderHeader()}
        {this.renderData()}
      </div>
    );
  }
}

export default Applications;

Example Child Component (titlesparcels.js)

To update when a new ID is selected, add event listening in the child:

import React, { Component } from 'react';

class titlesparcels extends Component {
  constructor(props){
    super(props);
    this.state = { currentId: props.id };
  }

  componentDidMount() {
    // Listen for update event from parent
    this.props.glEventHub._layoutManager.eventHub.on('update-data', (data) => {
      this.setState({ currentId: data.id });
      // Fetch new data based on currentId here
    });
  }

  componentWillUnmount() {
    // Clean up event listener to avoid memory leaks
    this.props.glEventHub._layoutManager.eventHub.off('update-data');
  }

  render() {
    return(
      <div>
        <h3>Titles & Parcels for ID: {this.state.currentId}</h3>
        {/* Your component content here */}
      </div>
    );
  }
}

export default titlesparcels;

Key Takeaways

  • Register components once: Avoid duplicate registration errors by registering components during component initialization.
  • Avoid global state: Use React state and Golden Layout's event system for data passing.
  • Update existing components: Instead of creating new tabs every time, update the props of existing ones via events.
  • Fix syntax errors: Small typos can break entire workflows—always check your console for errors!

内容的提问来源于stack exchange,提问作者Thomson Ignesious

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 05:37:39