javascript - 在 React 中单击按钮时,如何仅展开一个列表项(无挂钩)?
问题描述
我有一个学生列表,我想制作一个可扩展的列表视图。基本上每个学生都会有一个加号和减号按钮,每次点击它时,所有学生成绩的列表都会扩大。但是,到目前为止,当我单击其中一个按钮时,它会同时打开所有学生的成绩列表。
我似乎无法弄清楚如何解决此问题,以便当我单击特定学生时,它只会打开该学生的成绩。谁可以帮我这个事?我想我已经接近了,但我无法到达那里!
这是我的代码:
import React from 'react';
import Average from './Average';
import './App.css';
class App extends React.Component{
state = {
students: [],
error: null,
search: null,
open: false,
}
componentDidMount(){
fetch('https://api.hatchways.io/assessment/students')
.then(res => res.json())
.then(
(data) => {
this.setState({
students: data.students,
})
},
(error) => {
this.setState({ error });
})
}
handleChange = (e) => {
this.setState({ search: e.target.value });
}
togglePanel = e => {
this.setState({ open: !this.state.open })
}
render(){
let { search, students, open } = this.state;
const display = students.filter((student) => {
if(search == null)
return student;
else if(student.firstName.toLowerCase().includes(search.toLowerCase()) ||
student.lastName.toLowerCase().includes(search.toLowerCase())){
return student;
}
}).map((student, idx) => {
return (
<div className = "student-container" key = {student.id}>
<img className = "student-pic" src = {student.pic} alt = "pictures"/>
<div className = "student-mini">
<h1>{student.firstName.toUpperCase()} {student.lastName.toUpperCase()}</h1>
<p>Email: {student.email}</p>
<p>Company: {student.company}</p>
<p>Skill: {student.skill}</p>
<Average grades = {student.grades}/>
<button onClick = {(e) => this.togglePanel(e)}>{open ? '-' : '+'}</button>
<div>
<p>{open ? student.grades.map((grade, id) => {
return (
<p key = {id}>Test {id + 1}: {grade}%</p>
)
}): null}
</p>
</div>
</div>
</div>
)
})
return (
<div className = "gray-container">
<div className = "white-container">
<form>
<input onChange = {this.handleChange} type = "text" placeholder = "Search by
name">
</input>
</form>
<div>
{display}
</div>
</div>
</div>
)
}
}
export default App;
解决方案
您的每个可扩展面板都使用相同的单一open
状态来确定是否应该扩展它,这就是它们同时打开的原因。这里最简单的解决方案是让每个面板都有自己的状态。
理想情况下,您希望从地图的 return 语句中提取 JSX 以分离呈现单个学生面板的组件,例如StudentPanel
,将学生对象作为道具传递,并将open
状态和切换功能也移动到该组件。
更新:你会有这样的事情:
class StudentPanel extends React.Component {
state = {
open: false
}
togglePanel = e => {
this.setState(prevState => ({ open: !prevState.open }))
}
render() {
const { student } = this.props;
return (
<div className = "student-container" key = {student.id}>
// (...) rest of JSX
</div>
);
}
}
在render
你的App
你有:
(...).map(student => <StudentPanel student={student} />)
和open
属性,togglePanel
可以完全从App
组件中删除。
推荐阅读
- c++ - 首先调用复制构造函数,而不是仅在传递 R 值引用时移动构造函数
- python - 排序列表的实现类
- javascript - 在onClick上从另一个php将两个变量返回到两个不同的div
- linux - Linux:连接时的 USB 触发器仅在首次连接时触发。需要 `systemd --user damon-reload` 再次激活
- static-libraries - nim:使用静态库
- algorithm - 有人可以评估这个函数的时间复杂度吗
- google-cloud-platform - Bigquery DML 操作
- swift - 教程类型“NSNotification.Name”没有成员“UIResponder”中的 Swift 5 不起作用
- java - 使用 Java 将具有时区偏移的日期和时间转换为时间戳
- html - 如何在 CSS 中为 iframe 正确实现 margin-left?