首页 > 解决方案 > 如何在渲染之前将属性添加到通过 props- 传递的 HTML 标签?

问题描述

我有一些将 JSX 数组作为道具的代码。该组件应该确保所有 JSX 都按照它们在数组中出现的顺序呈现。为了做到这一点,我的所有组件都有一个可选的 onLoad 函数,它们可以作为道具。当我最初在父组件中创建 JSX 数组时,并没有添加此函数,因此我不必在所有这些不同的父类中编写相同的函数。所以我将它们传递给处理加载顺序的组件,但它需要一种将 onLoad 属性添加到数组中所有内容的方法。

我尝试通过数组进行映射并child.setAttribute在每个元素上使用,但出现错误:setAttribute is not a function

我也试过child.onLoad = this.childDidLoad导致错误:Cannot add property onLoad, object is not extensible

我试过传播,你应该在下面看到。这不会引发错误,但似乎永远不会添加该属性,因为永远不会到达该部分代码。

class StandardPage extends Component {
  static propTypes = {
    children: PropTypes.array.isRequired, // All child components to render
  };

  state = {
    childrenLoaded: 0, // Number of children loaded
  };

  /**
   * When this method is called, a child has updated.
   * Take previous value of number of children loaded, and add one.
   * Store as new value in state
   */
  childDidLoad() {
    const {childrenLoaded} = this.state;

    this.setState({
      childrenLoaded: childrenLoaded + 1,
    });
  }

  /**
   * Slice children array to only return those that have loaded, plus one.
   * THIS CONTAINS THE PROBLEM!!!
   * @return {array} JSX array
   */
  getLoaded() {
    const {childrenLoaded} = this.state;
    const {children} = this.props;

    this.childDidLoad = this.childDidLoad.bind(this);
    const loaded = children.slice(0, childrenLoaded + 1);

    return loaded.map((child) => {
      return {
        ...child, // THIS IS THE PROBLEM SPOT
        onLoad: this.childDidLoad,
      };
    });
  }

  /**
   * Visual component
   * @return {jsx}
   */
  render() {
    const components = this.getLoaded();

    return (
      <div className="page">
        <Nav>
          {components}
        </Nav>
      </div>
    );
  }
}

示例使用:

class ExamplePage extends Component {
  state = {
    children: [
      <Section
            key="origin"
            restEndpoint="origin"
            id={originID}
            bgColor={(isYellow) ? 'yellow' : 'white'}
            txtJustify={true}
          />,
      <Section
            key="funFacts"
            restEndpoint="funfacts"
            id={funFactID}
            bgColor={(isYellow) ? 'yellow' : 'white'}
            txtJustify={true}
          />
    ],
  };

  /**
   * Visual component
   * @return {jsx}
   */
  render() {
    const {children} = this.state;

    return (
      <StandardPage children={children} />
    );
  }
}

现在,第一个子组件被显示,没有其他子组件,因为 childDidLoad 方法永远不会被调用。

标签: javascripthtmlreactjsjsx

解决方案


return loaded.map((child) => {
    return React.cloneElement(child, { onLoad: this.childDidLoad });
});

这可能对您将方法作为道具传递给您的组件有用。如果没有帮助,我将在我的本地机器上设置一个测试以进行进一步调查。问候


推荐阅读