简体   繁体   中英

Accessing Parent Component Variable

I am trying to express my Openlayers application as a components based application. Having a single <Map /> component with childrens like <Marker /> , I need to access my <Map /> component's this.map property from the <Marker /> .

Take this markup from a representational component:

<Map center={[-1.81185, 52.44314]} zoom={6}>
    <Marker title="This is a marker" coordinate={[-1.81185, 52.44314]} />
</Map>

The <Map /> component:

export default class Map extends React.Component {

    static propTypes = {
        center: React.PropTypes.array.isRequired,
        zoom: React.PropTypes.number.isRequired
    }

    constructor(props) {
        super(props);
        this.map = null;
    }


    componentDidMount() {
        this.map = new ol.Map(/* code removed for brevity */);
    }

    renderChildren() {
        const { children } = this.props;

        if (!children) return;

        return React.Children.map(children, c => {
            return React.cloneElement(c, {
                map: this.map
            });
        })
    }

    render() {
        return <div id="map">{this.renderChildren()}</div>
    }

}

The <Marker /> component:

export default class Marker extends React.Component {

    static propTypes = {
        map: React.PropTypes.object,
        coordinate: React.PropTypes.array.isRequired,
        title: React.PropTypes.string
    }

    componentDidMount() {
        const { map, coordinate, title } = this.props;

        if (!map) return;

        var marker = createMarkerAndPlaceOn(map);
    }


    render() {
        return null;
    }
}

As you can see I tried passing the this.map property down, by cloning the element and give it the property.

However, because I need to rely on the DOM node #map to be rendered, I can first initialize my new ol.Map() in the <Map /> 's componentDidMount() method. This means my child component does not get the instance of this.map when rendering.

Is there any clean, non anti-pattern, way of achieving this?

You can store map in the state and it'll be passed down to the children as soon as it's ready.

constructor(props) {
    super(props);
    this.state = {
        map: null
    }
    this.renderChildren = this.renderChildren.bind(this);
 }


componentDidMount() {
    this.setState({map : new ol.Map()});
}

renderChildren() {
    const { children } = this.props;

    if (!children) 
        return;

    if(!this.state.map)
        return <div>Loading markers</div>

    return React.Children.map(children, c => {
        return React.cloneElement(c, {
            map: this.state.map
        });
    })
}

jsfiddle

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM