我的状态是这样的。这是一个内部有多个字段的对象。出于某些目的,我无法修改状态的结构。这是呈现整个列表的我的组件
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
每当我单击一个列表项时,它都会重新渲染所有列表项。有办法避免这种情况吗?理想情况下,仅应重新单击被单击的行。
答案 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
或考虑使用PureComponent
:https://reactjs.org/docs/react-api.html#reactpurecomponent