React子组件未随props.filterTime变更重渲染该如何修复?
问题根因
你当前friendsDisplay中存储的是页面首次加载时创建的Friend组件实例,这些实例创建时绑定的是初始值为Daily的filterTime。后续filterTime发生变化时,你既没有重新生成Friend组件,也没有更新已有实例的prop,因此子组件的filterTime永远停留在初始值,也不会触发重渲染。
修复方案
核心是不要把React组件实例直接存储在state中,正确做法是存储原始数据,在渲染阶段动态生成组件,保证每次渲染都传入最新的prop。
步骤1:修改state存储内容
将原来存储组件实例的friendsDisplay改为存储好友原始数据:
// Friends.js 原代码 const [friendsDisplay, setFriendsDisplay] = useState([]); // 修改为 const [friendsList, setFriendsList] = useState([]);
步骤2:调整fetchData逻辑,仅存储原始数据
拉取数据后不要直接生成Friend组件,只把好友的基础信息、是否为当前用户的标识存入state:
const fetchData = async() => { try{ let doc = await docRef.get(); let data = doc.data(); let friendsRaw = []; // 拉取所有好友的原始数据 for(let uid of data.Friends){ if(uid !== ""){ let friendData = await fetchUserFriendData(uid); friendsRaw.push({ uid: uid, UserFriend: friendData, isUser: false }) } } // 加入当前用户自身的数据 friendsRaw.push({ uid: uid, UserFriend: data, isUser: true }) // 把原始数据存入state setFriendsList(friendsRaw); }catch(error){ console.log(error); } }
步骤3:动态计算排序后的好友列表
使用useMemo监听friendsList和filterTime的变化,自动重新排序:
import { useMemo } from 'react'; // 在Friends组件内部加入这段逻辑 const sortedFriends = useMemo(() => { if(friendsList.length === 0) return []; // 拷贝数组避免直接修改原state return [...friendsList].sort((a, b) => { if(props.filterTime === "Daily"){ return a.UserFriend.XpEarnedToday > b.UserFriend.XpEarnedToday ? -1 : 1; } if(props.filterTime === "Weekly"){ return a.UserFriend.XpEarnedWeek > b.UserFriend.XpEarnedWeek ? -1 : 1; } if(props.filterTime === "Monthly"){ return a.UserFriend.XpEarnedMonth > b.UserFriend.XpEarnedMonth ? -1 : 1; } return -1; }) }, [friendsList, props.filterTime])
步骤4:渲染阶段动态生成Friend组件
每次渲染时根据排序后的数据生成新的Friend组件,传入最新的filterTime:
return ( <div className = "friendsContainer"> {sortedFriends.length > 0 && ( <div className = "friends"> {sortedFriends.map(item => ( <Friend key={item.uid} UserFriend={item.UserFriend} isUser={item.isUser} src={``} filterTime={props.filterTime} /> ))} </div> )} {sortedFriends.length === 1 && ( <> {sortedFriends.map(item => ( <Friend key={item.uid} UserFriend={item.UserFriend} isUser={item.isUser} src={``} filterTime={props.filterTime} /> ))} </> )} </div> );
内容的提问来源于stack exchange,提问作者Atakan Yigit
相关产品推荐
相关产品推荐

