前端小誌(轉型中)

一個用來記錄人老會忘記的地方

React with map中的eventhandler

2017年09月27日

這個問題好像不常遇到,但是今天被同事問到的時候還一時回答不出來。

問題淺顯易懂,在map function裡面的params要何如何傳出來parent。

一下就回答用callback啊,但是仔細想一想要怎麼傳哬,囧。

class Parent extends Component {
  ...
  handleClick = (e) => {
    // what to do
    ...
  }

  render() {
    return (
      <div>
        {
          this.props.children( child => (
            // I want child props ex: ID
            <div onClick={this.handleClick} />
          ))
        }
      </div>
    )
  }
}

先想了一個解決方法後開始google,看到這篇文章

Easy way

this.props.children( child => (
  <div onClick={ ()=> { this.handleClick(child.id); } } />
))

這就是一般人直覺會想到的做法,但並不是太好。這網路上有很多文章,反正會有slightly performance issue(rebind與pure component等問題),另外不好閱讀。

Better Way

class Parent extends Component {
  ...
  onChildClick = (id) => {
    ...
  }

  render() {
    return (
      <div>
        {
          this.props.children( child => (
            // I want child props ex: ID
            <Child onChildClick={this.onChildClick} />
          ))
        }
      </div>
    )
  }
}

class Child extends Component {
  ...
  handleClick = (e) => {
    this.props.onChildClick(this.props.id);
  }

  render() {
    return (
      <div onClick={this.handleClick} />
    )
  }
}

這例子看起來很蠢,不過現實中很少map裡面長這麼簡單的,以前都寫這種寫法,所以就不知道怎麼回答寫在同一層的XD。

不過我一開始認真想的是data-attr

class Parent extends Component {
  ...
  handleClick = (e) => {
    const cid = e.target.getAttribute("data-cid");
  }

  render() {
    return (
      <div>
        {
          this.props.children( child => (
            // I want child props ex: ID
            <div data-cid={child.id} onClick={this.handleClick} />
          ))
        }
      </div>
    )
  }
}

隱約記得在哪個文章看過(react官方網站?!人老了)

最後,因為專案都用semantic-react啦...可以直接傳出data,用久了難怪忘光XDD,看了一下source code,使用lodash的invoke

handleClick = (e) => {
  const { disabled } = this.props

  if (disabled) {
    e.preventDefault()
    return
  }

  _.invoke(this.props, 'onClick', e, this.props)
}

也算學到了新東西!!


展開Disqus
分類
最近文章
友站連結
© 2019 Ernie Yang