React项目如何通过API设置默认新闻分类及解决刷新问题
解决React新闻项目刷新页面重置分类的问题
问题描述
我开发了一个通过API获取数据的React新闻项目,点击对应按钮可展示对应分类的新闻(比如点击sports按钮显示体育新闻)。需求是页面首次加载时默认激活All分类,无需点击即可加载全部新闻,但当前实现存在问题:浏览体育新闻时刷新页面,会自动回到全部新闻,该如何解决?
解决方案
核心思路是把当前分类同步到URL的查询参数中,这样刷新页面时可以从URL读取当前分类,而不是每次都默认加载'all'。同时修复原代码中loading状态设置的时序问题,具体修改步骤如下:
- 新增状态
currentCategory,初始值从URL的category查询参数获取,无参数时默认设为'all' - 修改
fetchValue函数,更新分类状态的同时,通过history.pushState同步更新URL的查询参数 - 调整
useEffect的依赖为currentCategory,当分类变化时自动触发数据请求 - 可选:给当前激活的分类按钮添加样式,让用户直观看到当前选中的分类
修改后的代码
App组件
import React, { useEffect, useState } from "react"; import SpinnerLoad from './components/SpinnerLoad' import NewsItem from "./components/NewsItem"; import Category from "./components/data/Category" const App = () => { const [state, setState] = useState([]); const [loading, setLoading] = useState(false); // 从URL查询参数获取初始分类,无参数则默认'all' const initialCategory = new URLSearchParams(window.location.search).get('category') || 'all'; const [currentCategory, setCurrentCategory] = useState(initialCategory); const fetchValue = (category) => { // 发起请求前先显示加载状态 setLoading(false); fetch(`https://inshorts-api.herokuapp.com/news?category=${category}`) .then(res => res.json()) .then(res => { setState(res.data); setLoading(true); // 更新URL查询参数,同步当前分类 const searchParams = new URLSearchParams(window.location.search); searchParams.set('category', category); window.history.pushState({}, '', `${window.location.pathname}?${searchParams}`); // 更新当前分类状态 setCurrentCategory(category); }) .catch((error) => console.log(error)); }; const CategoryButton = ({ category }) => ( <button onClick={() => fetchValue(category)} style={{ textTransform: 'capitalize', // 给激活的按钮添加区分样式 backgroundColor: currentCategory === category ? '#007bff' : 'transparent', color: currentCategory === category ? '#fff' : 'inherit', border: 'none', padding: '8px 16px', margin: '0 4px', borderRadius: '4px', cursor: 'pointer' }} > {category} </button> ); // 监听分类变化,自动触发对应请求 useEffect(() => { fetchValue(currentCategory); }, [currentCategory]) return ( <> <div className="header-bg"> <h1 className="mb-3">News</h1> <div className="btns "> {Category.map((value, index) => { return <CategoryButton category={value} key={index} />; })} </div> </div> <div className="news"> <div className="container"> <div className="row"> { !loading ? <SpinnerLoad/> : state.map((data,index) => { return ( <NewsItem imageUrl={data.imageUrl} author={data.author} title={data.title} content={data.content} date={data.date} key={data.id} /> ); }) } </div> </div> </div> </> ); }; export default App;
NewsItem组件(无需修改)
import React from 'react' import clock from "../components/assets/img/Clock.svg" import user from "../components/assets/img/User.svg" const NewsItem = (props) => { const {imageUrl, title, content, date, author} = props return ( <div class="col-lg-4 col-md-6 col-12 p-2"> <div className="newsItem"> <img src={imageUrl} alt=''/> <div className="itemBody"> <p className='title'>{title}</p> <div className="line"></div> <p className='content'>{content}</p> <div className="itemfooter"> <h6><img src={clock} alt='clock'/>{date}</h6> <h6><img src={user} alt='user'/>{author}</h6> </div> </div> </div> </div> ) } export default NewsItem
内容的提问来源于stack exchange,提问作者user18134288
相关产品推荐
相关产品推荐

