当其他组件更改数据时,如何使组件重新生成数据



假设出于某种原因,我们不能让Parent组件保存人员数据集(或者在父组件中对此进行任何逻辑处理(,也不能使用原子。有没有其他方法可以让AnotherComponentThatShowsBookedPersonnel知道,由于数据发生了变异,是时候从API重新获取数据了?


const Parent = () => {
return (
<BookPersonnel />
<AnotherComponentThatShowsBookedPersonnel />
)
}
const BookPersonnel = () => {
const [personnel, setPersonnel] = useState<Personnel[]>([])
useEffect(() => {
const fetchPersonnel = async () => {
const response = await fetchPersonnelBookings()
setPersonnel(response)
}  

fetchPersonnel()
}, [])
const bookPersonnel = async (personnelId:number) => {
const response = await bookPersonnelById(personnelId)
setPersonnel(response)
}
return (
<List of personnel here>
<Button onClick={bookPersonnel}>Book personnel</Button>
)
}
export const AnotherComponentThatShowsBookedPersonnel = () => {
const [personnel, setPersonnel] = useState<Personnel[]>([])
useEffect(() => {
const fetchPersonnel = async () => {
const response = await fetchPersonnelBookings()
setPersonnel(response)
}  

fetchPersonnel()
}, [])
return (
<List of booked personnel here>
)
}

尝试事件总线模型,这里有一个简单的实现:

// useEventBus.ts
const eventBus:Record<string,(()=>void)[]> = {}
const useEventBus = (keyName:string)=>{
const triggerEvent = ()=>eventBus[keyName]?.forEach(fn=>fn())
const addCallback= (callback: ()=>void)=>{ 
eventBus[keyName] =  eventBus[keyName]||([] as (()=>void)[])
eventBus[keyName].push(callback)
return ()=>{
const index = eventBus[keyName].indexOf(callback)
if(index!==-1){
eventBus[keyName].splice(index,1)
}
}
}
return  {triggerEvent,addCallback}
}
// Where you mutate data
import useEventBus from 'useEventBus'
const BookPersonnel = () => {
const [personnel, setPersonnel] = useState<Personnel[]>([])
const {triggerEvent} = useEventBus('PERSONAL/CHANGED')
const mutateData = ()=> {
// after mutating data, create a event maunally
triggerEvent()
// 
}

return (
<List of personnel here>
<Button onClick={bookPersonnel}>Book personnel</Button>
)
}

// where you want to be notified when data modified
import useEventBus from 'useEventBus'
const AnotherComponentThatShowsBookedPersonnel = () => {
const [personnel, setPersonnel] = useState<Personnel[]>([])
const {addCallback} = useEventBus('PERSONAL/CHANGED')
useEffect(()=>{
const cleanFn = addCallback( ()=>{
// anything you want to do when data changed
})
// dispose this callback when component unmount
return cleanFn;
},[])
//......
return (
<List of booked personnel here>
)
}

还有更多像事件发射器这样的工具可以选择使用。

但我仍然相信,您可以将数据提升到这些组件的共享父级。

令人惊讶的是,还没有人说过这句话,但use反应useReducer/useContext挂钩。useReducer将是您的最佳选择,因为它允许您创建调度函数来更改reducers状态。与其在多个地方定义人员,不如将其定义为减速器状态。将这两个组件封装在该上下文减少器的提供程序中。然后,在这两个组件中,您都可以使用钩子访问状态值,即const {personnel} = usePersonnelContext()或类似的东西。因为你正在改变一个值,所以你不必踢任何一个组件来识别事情已经改变了。不过,我会去看看上面的反应文档,会比我更好地解释它!

最新更新