React中如何实现点击数组元素后单独显示该元素?代码求助
解决React中点击列表项显示对应内容的问题
刚从jQuery转React确实会有点不适应,毕竟React是状态驱动而非直接操作DOM的思路。你的核心问题是没法追踪点击的是哪篇帖子,而且直接在onClick里调用函数(比如handleClick(this))会导致组件一渲染就执行这个函数,而不是点击时才执行。下面一步步帮你修正代码:
1. 调整状态结构
首先,我们需要在state里保存被选中的帖子ID(或者整个帖子对象),而不是只用一个clicked布尔值——布尔值只能告诉我们“是否处于详情页”,但没法区分是哪篇帖子。修改state:
this.state = { error: null, isLoaded: false, posts: [], selectedPostId: null // 新增:保存选中的帖子ID,null表示没选中 };
2. 修正点击事件处理
在onClick里,我们需要传递当前点击的帖子ID给处理函数。这里有两种常用方式:
- 用箭头函数包裹,传递参数
- 用
bind绑定参数
推荐第一种,更直观。修改列表项的onClick:
<li key={"Post" + post.id} onClick={() => this.handleClick(post.id)} align="start">
然后更新handleClick函数,把选中的ID存入state:
handleClick(postId) { this.setState({ selectedPostId: postId }); }
3. 实现返回功能
返回按钮的作用就是清空selectedPostId,回到列表视图:
handleReturn() { this.setState({ selectedPostId: null }); }
(注意:React会自动根据state变化重新渲染,不需要手动调用this.render())
4. 调整渲染逻辑
根据selectedPostId来判断渲染列表还是单个帖子:
- 如果
selectedPostId不为null:找到对应的帖子并渲染详情,同时添加返回按钮 - 否则:渲染所有帖子列表
修改render里的判断逻辑:
render() { const { error, isLoaded, posts, selectedPostId } = this.state; if (error) { return <div>Error in loading</div>; } else if (!isLoaded) { return <div>Loading ...</div>; } else if (selectedPostId !== null) { // 找到选中的帖子 const selectedPost = posts.find(post => post.id === selectedPostId); return ( <div className="selectedPostContainer"> <button onClick={() => this.handleReturn()}>← 返回列表</button> <p className="title">User: {selectedPost.userId}<br/>{selectedPost.title}</p> <p className="body">Post ID: {selectedPost.id}</p> <br/> <p className="body">{selectedPost.body}</p> </div> ); } else { return ( <div className="postContainer"> <ol className="item"> {posts.map((post) => ( <li key={"Post" + post.id} onClick={() => this.handleClick(post.id)} align="start"> <div> <p className="title">{post.title}</p> <p className="body">{post.body}</p> </div> </li> ))} </ol> </div> ); } }
完整修改后的代码
import React, { Component } from 'react'; import './GetOnlinePosts.css'; class GetOnlinePosts extends Component { constructor(props) { super(props); this.state = { error: null, isLoaded: false, posts: [], selectedPostId: null // 保存选中的帖子ID }; this.handleClick = this.handleClick.bind(this); this.handleReturn = this.handleReturn.bind(this); // 别忘了绑定这个函数 } handleClick(postId) { this.setState({ selectedPostId: postId }); } handleReturn() { this.setState({ selectedPostId: null }); } componentDidMount() { fetch("https://jsonplaceholder.typicode.com/posts") .then(response => response.json()) .then( (result) => { this.setState({ isLoaded: true, posts: result }); }, (error) => { this.setState({ isLoaded: true, error }) }, ) } render() { const { error, isLoaded, posts, selectedPostId } = this.state; if (error) { return <div>Error in loading</div>; } else if (!isLoaded) { return <div>Loading ...</div>; } else if (selectedPostId !== null) { const selectedPost = posts.find(post => post.id === selectedPostId); return ( <div className="selectedPostContainer"> <button onClick={this.handleReturn}>← 返回列表</button> <p className="title">User: {selectedPost.userId}<br/>{selectedPost.title}</p> <p className="body">Post ID: {selectedPost.id}</p> <br/> <p className="body">{selectedPost.body}</p> </div> ); } else { return ( <div className="postContainer"> <ol className="item"> {posts.map((post) => ( <li key={"Post" + post.id} onClick={() => this.handleClick(post.id)} align="start"> <div> <p className="title">{post.title}</p> <p className="body">{post.body}</p> </div> </li> ))} </ol> </div> ); } } } export default GetOnlinePosts;
关键思路说明
和jQuery直接找DOM元素不同,React的核心是状态决定视图:
- 当你点击帖子时,我们把该帖子的ID存入state
- React检测到state变化,自动重新渲染组件
- 渲染时根据state里的
selectedPostId来决定显示列表还是单个帖子
这样就完全不需要手动操作DOM啦,慢慢适应这种思路就会越来越顺手~
内容的提问来源于stack exchange,提问作者Gianmaria Vinci
相关产品推荐
相关产品推荐

