ReactJS 删除通过计数创建的子元素
ReactJS remove child element created through count
我有两个组件,一个 TrackSection(父元素),它有一个按钮,每次单击它时都会创建一个 TrackItem(子元素)。子元素是通过变量 numTracks 构建的,每次单击按钮时该变量都会递增。添加按钮工作正常,但我在从数组中删除 TrackItem 时遇到问题。我尝试直接引用 track_items 但它不允许我这样做。
我对 React 和前端开发还很陌生。任何其他提示将不胜感激!
TrackSection.js
class TrackSection extends Component {
constructor(props) {
super(props);
this.state = {
numTracks: 0,
};
}
onAddTrack = () => {
this.setState({
numTracks: this.state.numTracks + 1,
});
};
onDeleteTrack = () =>{
//????
};
render() {
const track_items = [];
for (var i = 0; i < this.state.numTracks; i += 1) {
track_items.push(<TrackItem key={i} id={i} onDeleteTrack = {this.onDeleteTrack(i)}/>);
}
return (
<div>
<Button onClick={this.onAddTrack}>
+new track
</Button>
{track_items}
</div>
);
}
}
TrackItem.js
class TrackItem extends Component{
constructor(props){
super(props);
this.state = {
id: this.props.id,
name: '',
}
}
render(){
var onDeleteTrack = this.props.onDeleteTrack
return(
<Grid container direction="row">
<Grid item direction="column">
//Dummy
</Grid>
<button onClick={() => onDeleteTrack(this.props.id)}>Delete</button>
</Grid>
);
}}
小心不要在渲染函数中做太多逻辑,因为您当前的解决方案会在您每次添加新项目时重新创建所有 TrackItem。所以 React 不能做优化魔法。
第二点,现在你只有一个计数器,所以删除中间的一个元素可能不会产生你想要的效果。我假设轨道项目将有一些数据给他们。像名称等。因此只需将这些值存储在状态中并呈现每个项目。
这是一个示例解决方案,请根据您的需要进行修改:
class TrackSection extends Component {
constructor(props) {
super(props);
this.state = {
tracks: []
};
}
onAddTrack = () => {
// Probably not the best way to create a id
const randomId = Math.random().toString();
const newTrack = {
id: randomId,
name: "Some name" + randomId
};
const newTracks = [
// the tracks we allready have added
...this.state.tracks,
// add a new track to the end
newTrack
];
// Replace state
this.setState({
tracks: newTracks
});
};
onDeleteTrack = (id) => {
// Keeps all tracks that don't match 'id'
const tracksWithOutDeleted = this.state.tracks.filter(
(track) => track.id !== id
);
// Replace the tracks, so now its gone!
this.setState({
tracks: tracksWithOutDeleted
});
};
render() {
return (
<div>
<button onClick={this.onAddTrack}>+new track</button>
{
// Loop over tracks we have in state and render them
this.state.tracks.map((track) => {
return (
<TrackItem
id={track.id}
name={track.name}
onDeleteTrack={this.onDeleteTrack}
/>
);
})
}
</div>
);
}
}
和TrackItem.js:
class TrackItem extends Component {
render() {
const { onDeleteTrack, id, name } = this.props;
return (
<>
<button onClick={() => onDeleteTrack(id)}>Delete {name}</button>
</>
);
}
}
问题
您正在使用数组索引作为 React 键,并且 id
。当您从数组中删除一个元素时,您可以将其从数组中删除,但由于项目向上移动以填充“洞”,现在数组中的所有元素都具有不正确的“id”/索引值。
解决方案
不要使用映射数组索引作为 React 键。
示例解决方案像以前一样使用递增的 id,但也将数组存储在状态中。这允许您一致地增加 id 键 and 为每个元素保留一个静态 id。
class TrackItem extends Component {
constructor(props) {
super(props);
this.state = {
id: this.props.id,
name: ""
};
}
render() {
var onDeleteTrack = this.props.onDeleteTrack;
return (
<Grid container direction="row">
<Grid item direction="column">
//Dummy
</Grid>
<button onClick={() => onDeleteTrack(this.props.id)}>Delete {this.props.id}</button>
</Grid>
);
}
}
class TrackSection extends Component {
constructor(props) {
super(props);
this.state = {
tracks: [],
id: 0,
};
}
onAddTrack = () => {
this.setState(prevState => ({
tracks: [...prevState.tracks, prevState.id],
id: prevState.id + 1,
}));
};
onDeleteTrack = (id) =>{
this.setState(prevState => ({
tracks: prevState.tracks.filter(el => el !== id)
}))
};
render() {
return (
<div>
<button onClick={this.onAddTrack}>
+new track
</button>
{this.state.tracks.map(track => (
<TrackItem key={track} id={track} onDeleteTrack = {this.onDeleteTrack}/>
))}
</div>
);
}
}
我有两个组件,一个 TrackSection(父元素),它有一个按钮,每次单击它时都会创建一个 TrackItem(子元素)。子元素是通过变量 numTracks 构建的,每次单击按钮时该变量都会递增。添加按钮工作正常,但我在从数组中删除 TrackItem 时遇到问题。我尝试直接引用 track_items 但它不允许我这样做。
我对 React 和前端开发还很陌生。任何其他提示将不胜感激!
TrackSection.js
class TrackSection extends Component {
constructor(props) {
super(props);
this.state = {
numTracks: 0,
};
}
onAddTrack = () => {
this.setState({
numTracks: this.state.numTracks + 1,
});
};
onDeleteTrack = () =>{
//????
};
render() {
const track_items = [];
for (var i = 0; i < this.state.numTracks; i += 1) {
track_items.push(<TrackItem key={i} id={i} onDeleteTrack = {this.onDeleteTrack(i)}/>);
}
return (
<div>
<Button onClick={this.onAddTrack}>
+new track
</Button>
{track_items}
</div>
);
}
}
TrackItem.js
class TrackItem extends Component{
constructor(props){
super(props);
this.state = {
id: this.props.id,
name: '',
}
}
render(){
var onDeleteTrack = this.props.onDeleteTrack
return(
<Grid container direction="row">
<Grid item direction="column">
//Dummy
</Grid>
<button onClick={() => onDeleteTrack(this.props.id)}>Delete</button>
</Grid>
);
}}
小心不要在渲染函数中做太多逻辑,因为您当前的解决方案会在您每次添加新项目时重新创建所有 TrackItem。所以 React 不能做优化魔法。
第二点,现在你只有一个计数器,所以删除中间的一个元素可能不会产生你想要的效果。我假设轨道项目将有一些数据给他们。像名称等。因此只需将这些值存储在状态中并呈现每个项目。
这是一个示例解决方案,请根据您的需要进行修改:
class TrackSection extends Component {
constructor(props) {
super(props);
this.state = {
tracks: []
};
}
onAddTrack = () => {
// Probably not the best way to create a id
const randomId = Math.random().toString();
const newTrack = {
id: randomId,
name: "Some name" + randomId
};
const newTracks = [
// the tracks we allready have added
...this.state.tracks,
// add a new track to the end
newTrack
];
// Replace state
this.setState({
tracks: newTracks
});
};
onDeleteTrack = (id) => {
// Keeps all tracks that don't match 'id'
const tracksWithOutDeleted = this.state.tracks.filter(
(track) => track.id !== id
);
// Replace the tracks, so now its gone!
this.setState({
tracks: tracksWithOutDeleted
});
};
render() {
return (
<div>
<button onClick={this.onAddTrack}>+new track</button>
{
// Loop over tracks we have in state and render them
this.state.tracks.map((track) => {
return (
<TrackItem
id={track.id}
name={track.name}
onDeleteTrack={this.onDeleteTrack}
/>
);
})
}
</div>
);
}
}
和TrackItem.js:
class TrackItem extends Component {
render() {
const { onDeleteTrack, id, name } = this.props;
return (
<>
<button onClick={() => onDeleteTrack(id)}>Delete {name}</button>
</>
);
}
}
问题
您正在使用数组索引作为 React 键,并且 id
。当您从数组中删除一个元素时,您可以将其从数组中删除,但由于项目向上移动以填充“洞”,现在数组中的所有元素都具有不正确的“id”/索引值。
解决方案
不要使用映射数组索引作为 React 键。
示例解决方案像以前一样使用递增的 id,但也将数组存储在状态中。这允许您一致地增加 id 键 and 为每个元素保留一个静态 id。
class TrackItem extends Component {
constructor(props) {
super(props);
this.state = {
id: this.props.id,
name: ""
};
}
render() {
var onDeleteTrack = this.props.onDeleteTrack;
return (
<Grid container direction="row">
<Grid item direction="column">
//Dummy
</Grid>
<button onClick={() => onDeleteTrack(this.props.id)}>Delete {this.props.id}</button>
</Grid>
);
}
}
class TrackSection extends Component {
constructor(props) {
super(props);
this.state = {
tracks: [],
id: 0,
};
}
onAddTrack = () => {
this.setState(prevState => ({
tracks: [...prevState.tracks, prevState.id],
id: prevState.id + 1,
}));
};
onDeleteTrack = (id) =>{
this.setState(prevState => ({
tracks: prevState.tracks.filter(el => el !== id)
}))
};
render() {
return (
<div>
<button onClick={this.onAddTrack}>
+new track
</button>
{this.state.tracks.map(track => (
<TrackItem key={track} id={track} onDeleteTrack = {this.onDeleteTrack}/>
))}
</div>
);
}
}