React - 子组件作为行为?

时间:2017-12-04 17:13:23

标签: reactjs

我试图通过子装饰器将功能注入父组件。例如,

<OpenLayers>
    <GeoJsonLayer url="https://openlayers.org/en/master/examples/data/geojson/countries.geojson"/>
</OpenLayers>

我必须使用上下文来执行此操作,但我将其解释为警告标志,因为有许多地方说,“如果您正在使用上下文你可能做错了什么&#39;。似乎child.props.parent应该已经存在,但同样,我正在寻找的事实必须是另一个警示标志。

也许父母负责迭代它的孩子并调用修改自己的方法?但那会在哪里完成?  如何访问组件实例?

如果孩子没有明确知道孩子,孩子如何修改父母?我正在寻找允许子组件修改父组件行为的现有模式,该组件不会使用&#34; context&#34;来调用。

以下是我迄今为止尝试过的两种方法。第一个似乎是更好的设计,但第二个允许我通过引入子组件扩展功能(例如):

    // one alternative is to not use child components but properties...
    this.props.geoJsonUrl && GeoJsonLayer.addGeoJsonLayer(map, this.props.geoJsonUrl);

    // another is to use child components and pass parent to a handler..
    Children.forEach(this.props.children, c => {
        c;
        if (typeof c === "string") return;
        if (typeof c === "number") return;
        let child: any = c;
        if (child.type === GeoJsonLayer) {
            GeoJsonLayer.addGeoJsonLayer(map, c.props.url);
        }
    });

    // I would prefer that the child trigger a cascading event that the parent could receive
    // and process

仅使用道具:

        <OpenLayers
            orientation={orientation}
            controls={{ mousePosition: true }}
            bingImagerySet="AerialWithLabels"
            labels={true}
            setCenter={setCenter}
            center={this.state.center}
            zoom={this.state.zoom}
            geoJsonUrl="http://openlayers.org/en/master/examples/data/geojson/countries.geojson"/>

使用孩子:

        <OpenLayers
            orientation={orientation}
            controls={{ zoom: true, zoomToExtent: true }}
            setCenter={setCenter}
            center={this.state.center}
            zoom={this.state.zoom}
            osm={false}>
            <GeoJsonLayer url="http://openlayers.org/en/master/examples/data/geojson/countries.geojson" />
        </OpenLayers>

2 个答案:

答案 0 :(得分:2)

您可以将prop onMount传递给带有函数的子组件。然后,在孩子的componentDidMount()中,您可以调用此功能。这个基本原则代表从孩子到父母的任何沟通。您实现了一个属性,该属性接收某个事件的处理程序,然后在事件发生时调用该处理程序。

修改:再看一遍后,我想我更了解所需的用例。

您希望允许OpenLayers组件的用户以组合方式挑选和选择图层,而不必担心父级中实际图层的连接。

您可以透明地将类似接口的对象传递给父级实现的子级。渲染子组件时将添加此属性。

class OpenLayers extends React.Component {
  constructor(props) {
    super(props);
    this.state = { };
    this.layerApi = {
      setupGeoJsonLayer: ({ url }) => // do something with state etc.
    };
  }

  render() {
    const { layerApi } = this;
    const { children } = this.props;
    return (
      <div> 
        { 
          !children ? null : React.Children(children, child => 
            React.cloneElement(child, { layerApi }))
        }
      </div>
    )
  }
}

class GeoJsonLayer extends React.Component {
  componentDidMount() {
    this.props.layerApi.setupGeoJsonLayer(this.props);
  }

  componentWillReceiveProps(next) {
    if (next.props.url !== this.props.url)
      this.props.layerApi.setupGeoJsonLayer(next.props);
  }

  render() {
    // what is rendered here?
  }
}

现在,每个图层都可以根据在道具中传递的父级API来操纵父级。

您必须确保父OpenLayers相应地触发其渲染周期。此外,每个层很可能都有一个空的render()方法,因为它们依赖于父级来呈现内容,并且仅用于修改父级的渲染输出。由于这些原因,我认为道具的方法可能更好。

答案 1 :(得分:2)

看看Lifting State Up

你会有某种LayerController在其状态中有一个层列表,并且应该在每个Layer的mount上调用addLayer,然后,将层列表传递给中间的OpenLayers组件通过道具。