反应所有列表项重新呈现

时间:2019-01-10 08:32:26

标签: reactjs create-react-app

我的状态是这样的。这是一个内部有多个字段的对象。出于某些目的,我无法修改状态的结构。这是呈现整个列表的我的组件

import React, { Component } from 'react'
import styled from 'styled-components';
import FoodListItem from '../Food-List-Item'

const Wrapper = styled.div`
  width: 300px;
  max-width: 300px;
`

const Button = styled.button`
  width: 300px;
  text-align: center;
  padding: 1em;
  border: 1px solid #eee;
  background-color: #ffffff;
  text-transform: uppercase;
  font-size: 1em;
  border-radius: 4px;
  cursor: pointer;
  transition: background-color 0.45s ease-in-out, border 0.45s ease-in-out;

  :hover {
    background-color: #eee;
    border: 1px solid black;
  }
`

class FoodList extends Component {
  state = {
    data: {
      e5d9d9f5: {
        label: 'ice cream',
        isDelicious: true,
        isHealthy: false,
      },
      a9ba692b: {
        label: 'pizza',
        isDelicious: true,
        isHealthy: false,
      },
      ze128a47: {
        label: 'spinach',
        isDelicious: false,
        isHealthy: true,
      },
    },
  }

  renderListItems = () => {
    const { data } = this.state
    return Object.keys(data).map((key) => {
      return <FoodListItem 
        key={key} 
        {...data[key]}
        id={key}
        handleDecliousChange={this.handleDecliousChange}
        handleHealthyChange={this.handleHealthyChange} 
      />
    })
  }

  handleDecliousChange = (id) => {
    this.setState(state => ({
      data: {
        ...state.data,
        [id]: {
          ...state.data[id],
          isDelicious: !state.data[id].isDelicious
        }
      }
    }))
  }

  handleHealthyChange = (id) => {
    this.setState(state => ({
      data: {
        ...state.data,
        [id]: {
          ...state.data[id],
          isHealthy: !state.data[id].isHealthy
        }
      }
    }))
  }

  handleShowAppState = () => {
    console.log(this.state.data)
  }

  render() {
    return (
      <Wrapper>
        {this.renderListItems()}
        <Button type="button" onClick={this.handleShowAppState}>Show App State</Button>
      </Wrapper>
    )
  }
}

export default FoodList;

这里是呈现单个列表项的组件

    import React from 'react'
import styled from 'styled-components'

const Title = styled.p`
  text-transform: uppercase;
  font-weight: bold;
`

const Item = styled.div`
  padding: 1em 1em 1em 0em;
  padding-left: ${props => props.isDelicious ? '30px': '0px'}
  margin-bottom: 2em;
  background-color: ${props => props.isHealthy ? 'green' : 'gray'};
  transition: background-color 0.45s ease-in-out, padding-left 0.45s ease-in-out;
  color: #ffffff;
`

class FoodListItem extends React.PureComponent {
  deliciousFn = () => {
    this.props.handleDecliousChange(this.props.id)
  }

  healthyFn = (id) => {
    this.props.handleHealthyChange(this.props.id)
  }

  render() {
    console.log('render called', this.props.label);
    const {
      id,
      label, isDelicious, isHealthy,
      handleDecliousChange, handleHealthyChange
    } = this.props
    return (
      <Item isHealthy={isHealthy} isDelicious={isDelicious}>
        <Title>{label}</Title>
        <div>
          <input type="checkbox" checked={isDelicious} onChange={this.deliciousFn} />
          <label><code>isDelicious</code></label>
        </div>
        <div>
          <input type="checkbox" checked={isHealthy} onChange={this.healthyFn} />
          <label><code>isHealthy</code></label>
        </div>
      </Item>
    )
  }
}

export default FoodListItem

每当我单击一个列表项时,它都会重新渲染所有列表项。有办法避免这种情况吗?理想情况下,仅应重新单击被单击的行。

1 个答案:

答案 0 :(得分:1)

您应该实现shouldComponentUpdate来处理FoodListItem中组件的输出:

  

使用shouldComponentUpdate()来让React知道组件的输出是否   不受当前状态或道具变更的影响。默认值   行为是在每一个状态变化时以及在广大   大多数情况下,您应该依靠默认行为。

class FoodListItem extends React.Component {
  //...
  shouldComponentUpdate(nextProps) {
     return (
       this.props.isDelicious !== nextProps.isDelicious ||
       this.props.isHealthy !== nextProps.isHealthy
     )
  }
  //...
}

参考:https://reactjs.org/docs/react-component.html#shouldcomponentupdate

或考虑使用PureComponenthttps://reactjs.org/docs/react-api.html#reactpurecomponent