Reputation: 1692
I have a component which is address of company. Each address is an object which is consists of two fields address and metro. (I get rid of some code with declaring Props and State because it doesn't matter)
class CompanyAddress extends React.Component<Props, State> {
constructor(props:Props) {
super(props);
this.state = {address:''}
}
changeAddress = (text:string) => {
this.setState({address: text});
this.props.changeAddress(this.props.index, text, this.state.metro);
}
changeMetro = (metro:{id: Number, name: string}) => {
this.setState({metro:metro});
this.props.changeAddress(this.props.index, this.state.address, metro.id);
}
render() {
return (
<View style={styles.container}>
<TextInput
autoCompleteType="name"
placeholder={("address " + (this.props.num))}
maxLength={50}
style={[styles.address, {marginTop: 5}]}
onChangeText={(text) => { this.changeAddress(text)}}
/>
<TouchableOpacity
style={styles.address}
onPress={() => this.props.navigation.navigate('MetroList', {changeMetro: this.changeMetro})}
>
{this.state.metro ? (
<Text style={[styles.metroText, {color: 'black'}]}>
{this.state.metro.name}
</Text>
) : (
<Text style={styles.metroText}>
Nearest metro
</Text>
)}
</TouchableOpacity>
{this.props.num != 1 ? (
<AntDesign
onPress={() => {this.props.removeAddress(this.props.index)}}
style={styles.minus}
name="minus"
size={24}
color="black"
/>
) : null}
</View>
);
}
}
I also have parrent component with array of addreses and 3 methods addAddress, changeAddress and removeAddress.
class CompanyAddresses extends React.Component<Props, State> {
constructor(props:Props) {
super(props);
this.state = {
addresses: [{address: ''}]
}
}
addAddress = () => {
this.setState({addresses: [...this.state.addresses, {address: ''}]});
}
changeAddress = (elemIndex:number, address:string, metro:number) => {
let addresses = this.state.addresses;
addresses[elemIndex] = {address: address, metro: metro};
this.setState({addresses:addresses});
}
removeAddress = (elemIndex:number) => {
const filtered = this.state.addresses.filter((value, index) => {
return index != elemIndex;
});
console.log(filtered);
this.setState({addresses: filtered})
}
render() {
return (
<View style={styles.container}>
{this.state.addresses.map((address:any, index) =>
<CompanyAddress
changeAddress={this.changeAddress}
removeAddress={this.removeAddress}
navigation={this.props.navigation}
key={index}
index={index}
num={index + 1}
/>
)}
{this.state.addresses.length < 5 ? (
<Button title="add address" onPress={this.addAddress} />
) : null}
</View>
);
}
}
addAdress and changeAddress work well but removeAddress does not. This method doest not render right addresses after render.
For example, I added 3 addresses with name "one", "two" and "three". Then I removed address with name "two" but I see two adresses with name "one" and "two".
The most ineteresting thing is the fact that I see correct array with addresses "one" and "three" in console just before setState method.
Upvotes: 1
Views: 593
Reputation: 14355
The state is almost certainly being updated correctly. The issue you're seeing is due to the fact that your key
inside the map
is the index of the array. You can see in the docs that using the index as the key
is not recommended, and this is a major reason.
We don’t recommend using indexes for keys if the order of items may change. This can negatively impact performance and may cause issues with component state.
You've modified the array so that what was at index 2
is now at index 1
. This causes react to think that only the third item should be removed, and nothing else needs to change.
Upvotes: 1