Как правильно обновлять большие состояния в React Native?
Я пишу небольшое приложение ReactNative, которое позволяет пользователям приглашать людей на мероприятия.
Дизайн включает в себя список приглашенных, каждый из которых сопровождается флажком, используемым для приглашения / удаления приглашенного. Еще один флажок вверху списка, который выполняет массовое приглашение / удаление всех приглашенных одновременно. Наконец, кнопка будет в конечном итоге использоваться для отправки приглашений.
Поскольку состояние каждого из этих элементов зависит от изменений, внесенных другим, мне часто требуется заново отображать весь пользовательский интерфейс всякий раз, когда пользователь выполняет действие над одним из них. Но хотя это работает правильно, это вызывает у меня немало проблем с производительностью, как показано в этом видео
Вот код, который я использую:
import React, { Component } from 'react';
import { Container, Header, Title,
Content, Footer, FooterTab,
Button, Left, Right,
Center, Body, Text, Spinner, Toast, Root , CheckBox, ListItem, Thumbnail} from 'native-base';
import { FlatList, View } from 'react-native';
export default class EventInviteComponent extends Component {
constructor(props) {
super(props);
console.disableYellowBox = true;
this.state = {
eventName: "Cool Outing!",
invitees:[]
}
for(i = 0; i < 50; i++){
this.state.invitees[i] = {
name: "Peter the " + i + "th",
isSelected: false,
thumbnailUrl: 'https://is1-ssl.mzstatic.com/image/thumb/Purple111/v4/62/08/7e/62087ed8-5016-3ed0-ca33-50d33a5d8497/source/512x512bb.jpg'
}
}
this.toggelSelectAll = this.toggelSelectAll.bind(this)
}
toggelSelectAll(){
let invitees = [...this.state.invitees].slice();
let shouldInviteAll = invitees.filter(invitee => !invitee.isSelected).length != 0
let newState = this.state;
newState = invitees.map(function(invitee){
invitee.isSelected = shouldInviteAll;
return invitee;
});
this.setState(newState);
}
render() {
let invitees = [...this.state.invitees];
return (
<Root>
<Container>
<Content>
<Text>{this.state.eventName}</Text>
<View style={{flexDirection: 'row', height: 50, marginLeft:10, marginTop:20}}>
<CheckBox
checked={this.state.invitees.filter(invitee => !invitee.isSelected).length == 0}
onPress={this.toggelSelectAll}/>
<Text style={{marginLeft:30 }}>Select/deselect all</Text>
</View>
<FlatList
keyExtractor={(invitee, index) => invitee.name}
data={invitees}
renderItem={(item)=>
<ListItem avatar style={{paddingTop: 20}}>
<Left>
<Thumbnail source={{ uri: item.item.thumbnailUrl}} />
</Left>
<Body>
<Text>{item.item.name}</Text>
<Text note> </Text>
</Body>
<Right>
<CheckBox
checked={item.item.isSelected}/>
</Right>
</ListItem>}/>
</Content>
<Footer>
<FooterTab>
<Button full
active={invitees.filter(invitee => invitee.isSelected).length > 0}>
<Text>Invite!</Text>
</Button>
</FooterTab>
</Footer>
</Container>
</Root>);
}
}
2 ответа
В вашем коде, в методе класса toggelSelectAll() {...}
вы изменяете состояние напрямую, используя this.state = ...
, чего стоит избегать. Использовать только this.state = ...
в вашем классе constructor() {...}
для инициализации состояния, и вы должны использовать только this.setState({...})
обновить состояние в другом месте.
Не уверен, что это должно помочь вашей производительности, но попробуйте заменить toggelSelectAll()
со следующим:
toggelSelectAll() {
const {invitees} = this.state;
const areAllSelectedAlready = invitees.filter(({isSelected}) => !isSelected).length === 0;
this.setState({
invitees: invitees.map(invitee => ({
...invitee,
isSelected: !areAllSelectedAlready
}))
});
}
Удачи! И, дайте мне знать, если вы хотите, чтобы я реорганизовал код выше, чтобы удалить 2-й this.state = ...
в вашем конструкторе (чего, опять же, следует избегать при написании React).
Я предлагаю:
Разделите ваш код, создав несколько компонентов, чтобы у вас не было
render()
Использование Redux для хранения приглашенного / глобального состояния, так что вы можете выбрать, какие компоненты следует перерисовать в случае изменений
Это хороший способ изучить React Native!