通过嵌套子组件映射

时间:2017-09-23 06:01:16

标签: reactjs

我正在尝试将新属性添加到顶级组件中的嵌套子元素。

我的高级组件名为Photo.js

import React, {Component} from 'react';
import PropTypes from 'prop-types';

export default class Photo extends Component{

  constructor(props){
    super(props);
    this.onHandleLoad = this.onHandleLoad.bind(this);

    this.state = {
      isLoaded:false
    }
  }

  onHandleLoad(event){
    this.setState({
      isLoaded:true
    })
  }

  render(){
    const {children} = this.props;
    return(
      <div className="photo-container">
        {children}
      </div>
    )
  }
}

以下是我如何添加儿童内容。

   <Photo >
      <Link to='/bla' className="slide-show-link">
        <img src={photo.photo} alt={`${photo.title} photo`}/>
      </Link>
    </Photo>

它并不总是和孩子们一样。有时它可能是嵌套的更多级别,但它总是有一个 img 元素。 我想要一种能够映射所有嵌套元素并找到img元素并为其添加自定义道具的方法。

我要添加的道具是onLoad = {this.onHandleLoad)所以它会调用具有正确范围的Photo内的onHandleLoad。

我看过React.Children.map,但只返回第一个元素而不是嵌套元素。 img可能会降低1级或更多。 我怎样才能做到这一点。正在研究递归映射,但不确定是否可行。是否有一个内置的方法来处理这个?

1 个答案:

答案 0 :(得分:2)

执行此操作的最佳方法可能是使用redux之类的操作,并为每个图像加载调度操作。但如果您目前没有使用它,则需要进行大量重构。

还有另一种适合的方式,即context。有many warnings about using context,但由于您只提供回调,因此风险不大。

上下文将允许您的父组件向下传递回调任意数量的级别,而不必通过每个级别传递道具。

-

首先将childContextTypesgetChildContext添加到您的父组件:

export default class Photo extends Component {
  static childContextTypes = {
    onHandleLoad: PropTypes.func
  };

  constructor(props) {
    super(props);

    this.state = {
      isLoaded: false
    }
  }

  getChildContext() {
    return {
      onHandleLoad: this.onHandleLoad
    };
  }

  onHandleLoad = (event) => {
    this.setState({
      isLoaded: true
    })
  }

  render() {
    const {children} = this.props;
    return(
      <div className="photo-container">
        {children}
      </div>
    )
  }
}

然后,您需要在<img>周围使用子组件包装器,以使用contextTypes挂钩到父上下文中:

class PhotoImage extends Component {
  static contextTypes = {
    onHandleLoad: PropTypes.func
  }

  static propTypes = {
    photo: PropTypes.string,
    title: PropTypes.string
  }

  render() {
    return (
      <img
        src={photo}
        alt={`${title} photo`}
        onLoad={this.context.onHandleLoad}
      />
    )
  }
}