简体   繁体   中英

Passing down onClick Functions: [ESLINT] JSX props should not use .bind() (react/jsx-no-bind)

I'm currently writing my first react application and my ESLINT is telling me that I shouldn't be using .bind() on JSX props. I understand that this is because bind is creating new functions and therefore negatively affecting performance. However i am not sure how to refactor this to eliminate this error.

How can i pass the element I have clicked to the function without using a bind?

ForecastPage.jsx:

import React from 'react'
import api from '../shared/api'
import ForecastBox from './ForecastBox'
import DropdownSelector from './DropdownSelector'

const regions = [
  {
    name: 'Santa Cruz',
    id: '2958',
    spots:
    [
      { name: 'Steamer Lane', id: '4188' },
      { name: 'Four Mile', id: '5023' },
      { name: 'Waddell Creek', id: '5021' },
      { name: 'Mitchell\'s Cove', id: '5028' },
      { name: '26th Ave', id: '5030' },
    ],
  },
  {
    name: 'North Orange Country',
    id: '2143',
    spots:
    [
      { name: 'Newport', id: '1241' },
      { name: 'HB', id: '3421' },
    ],
  },
]

class ForecastPage extends React.Component {

  constructor(props) {
    super(props)
    this.state = {
      selectedRegion: null,
      selectedSpot: null,
      forecast: null,
    }

    this.regionSpotList = regions
    this.updateSpot = this.updateSpot.bind(this)
    this.updateRegion = this.updateRegion.bind(this)
  }

  updateRegion(region) {
    this.setState({
      selectedRegion: region,
      forecast: null,
    })

    api.fetchSpot(region.id)
    .then((forecast) => {
      this.setState({
        forecast,
      })
    })
  }

  updateSpot(spot) {
    this.setState({
      selectedSpot: spot,
      forecast: null,
    })

    api.fetchSpot(spot.id)
    .then((forecast) => {
      this.setState({
        forecast,
      })
    })
  }

  render() {
    return (
      <div>
        <div className="container-fluid row region-spot-select">
          <DropdownSelector
            options={this.regionSpotList}
            onSelect={this.updateRegion}
            title={this.state.selectedRegion == null ? 'Select Your Region' : this.state.selectedRegion.name}
            keyName={'region-selector'}
            id={'region-selector-dropdown'}
          />
          {this.state.selectedRegion != null &&
            <DropdownSelector
              options={this.state.selectedRegion.spots}
              onSelect={this.updateSpot}
              title={this.state.selectedSpot == null ||
              !this.state.selectedRegion.spots.includes(this.state.selectedSpot) ?
              'Select A Spot' :
              this.state.selectedSpot.name}
              keyName={'spot-selector'}
              id={'spot-selector-dropdown'}
            />
          }
        </div>
        <div>
          {!this.state.forecast ?
            <div>
              Select A Region
            </div>
          : <ForecastBox forecast={this.state.forecast} /> }
        </div>
      </div>
    )
  }
}

export default ForecastPage

DropdownSelector.jsx

// @flow

import React from 'react'
import PropTypes from 'prop-types'
import { DropdownButton, MenuItem } from 'react-bootstrap'

type Props = {
  options: Object,
  onSelect: Function,
  title: string,
  keyName: string,
  id: string,
}

const DropdownSelector = ({ title, options, keyName, id, onSelect }: Props) =>
  <div className="content">
    <div className="btn-group">
      <DropdownButton
        bsStyle={'primary'}
        title={title}
        key={keyName}
        id={id}
      >
        {options.map(element =>
          <MenuItem
            key={element.name}
            eventKey={element.name}
            // eslint-disable-next-line
            onClick={onSelect.bind(null, element)}
          >
            {element.name}
          </MenuItem>,
          )
        }
      </DropdownButton>
    </div>
  </div>


DropdownSelector.defaultProps = {
  id: null,
}

DropdownSelector.propTypes = {
  options: PropTypes.instanceOf(Object).isRequired,
  title: PropTypes.string.isRequired,
  onSelect: PropTypes.func.isRequired,
  keyName: PropTypes.string.isRequired,
  id: PropTypes.string,
}

export default DropdownSelector

You could also use an arrow function which would accomplish the same thing, so something like

onClick={(event) => this.props.onSelect(null, element)}

However, it has the same potential negative performance problem you mentioned. The React docs are very good in this area and enumerate your options and their pro's and cons: https://facebook.github.io/react/docs/handling-events.html

  • Updated to this.props.onSelect , forgot that you were passing that in as a prop as opposed to defining it on the component itself. And if you're not using the event object, perhaps just use

     onClick={() => this.props.onSelect(null, element)} 

尝试亚历克斯的答案,但只是onSelect,不带“ this”。

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