reactjs - 我在我的应用程序中使用带有 useContext 和 useReducer 的 typescript 使用 React,但由于某种原因,单击不会触发调度
问题描述
我有两个列表显示为来自一个初始对象列表的卡片。这个想法是在单击星号按钮时更改每个卡片列表项目中的值“最喜欢”,以便不喜欢的项目出现在不喜欢的项目列表中,而最喜欢的项目出现在最喜欢的项目列表中。我有一个文件 dataContext.tsx 是这样的:
import Data from './data.json'
let rawData: Bot[] = [...Data]
rawData.forEach( item => item.favorite = false )
export function createDataCtx<StateType, ActionType>(
reducer: Reducer<StateType, ActionType>,
initialState: StateType
) {
const defaultDispatch: Dispatch<ActionType> = () => initialState
const ctx = createContext({
state: initialState,
dispatch: defaultDispatch, // just to mock out the dispatch type and make it not optioanl
})
function Provider(props: PropsWithChildren<{}>) {
const [state, dispatch] = useReducer<Reducer<StateType, ActionType>>(reducer, initialState)
return <ctx.Provider value={{ state, dispatch }} {...props} />
}
return [ctx, Provider] as const
}
export const initialState = [...rawData]
type AppState = typeof initialState
type Action =
| { type: 'favorite', shortName: string }
| { type: 'unFavorite', shortName: string }
export function reducer(state: AppState, action: Action): AppState {
switch(action.shortName){
case 'favorite':
console.log('favorite action triggered!!')
return state.map( (item: Bot) => item.shortName === action.shortName // will have to map the elements with the index when using it so we van pass the index
? {...item, favorite: true}
: item
)
case 'unFavorite':
console.log('unFavorite action triggered!!')
return state.map( (item: Bot) => item.shortName === action.shortName // will have to map the elements with the index when using it so we van pass the index
? {...item, favorite: false}
: item
)
default:
return state
}
}
我在应用程序组件中像这样使用我的 Provider:
function App() {
const [ , DataProvider] = createDataCtx(reducer, initialState)
return (
<DataProvider>
<ThemeProvider theme={Theme}>
<AppStyles>
<Router>
<Header />
<Content />
</Router>
</AppStyles>
</ThemeProvider>
</DataProvider>
);
}
然后我在另一个名为 Cards.tsx 的组件中使用上下文,如下所示:
const [ctx, DataProvider] = createDataCtx(reducer, initialState)
const DataContext = ctx
const Cards = () => {
const {state, dispatch } = useContext(DataContext)
const faveBotsList = state.filter( item => item.favorite === true)
const unfaveBotsList = state.filter( item => item.favorite === false )
return (
<CardsStyles>
<CardsRow>
<FavTitle>Favorites</FavTitle>
</CardsRow>
<FavWrap>
{faveBotsList.map((item) => (
<BotCard
key={item.shortName}
favorite={item.favorite}
name={item.name}
shortName={item.shortName}
onStarClick={ () => dispatch({type: 'unFavorite', shortName: item.shortName}) }
/>
))}
</FavWrap>
<CardsWrap>
{unfaveBotsList.map((item) => (
<BotCard
key={item.shortName}
favorite={item.favorite}
name={item.name}
shortName={item.shortName}
onStarClick={ () => dispatch({type: 'favorite', shortName: item.shortName}) }/>
))}
</CardsWrap>
</CardsStyles>
)
}
如果您想查看它,这里是“BotCard”组件代码:
const BotCard = (props: any) => {
const { favorite, name, shortName, onStarClick } = props
return (
<StyledBCard className='col-sm-4 col-md-3 col-lg-2'>
<Row>
<FavoriteStar favorite={favorite} className='float-left' onStarClick={onStarClick} />
</Row>
<Row className='justify-content-center'>
<BotImage imageSrc={TestImage} />
</Row>
<Row>
<BotName>{name}</BotName>
</Row>
<Row>
<BotShortName>{shortName}</BotShortName>
</Row>
</StyledBCard>
)
}
'onStarClick' 属性被传递给一个子组件,该子组件将它传递给它的子组件,在那里它被传递给一个样式化组件按钮的 'onClick' 属性。但是点击不会触发调度。我没有看到没有正确实施的内容。
解决方案
我认为问题在于您在传递调度时正在调用调度。这应该是正确的方法:
<BotCard
key={item.shortName}
favorite={item.favorite}
name={item.name}
shortName={item.shortName}
dispatch={dispatch}
/>
然后,在孩子中调用它:
<button
onClick={() => dispatch({type: 'favorite', shortName: item.shortName})}
>
A button
</button>
推荐阅读
- regex - Laravel 中的正则表达式,如何允许 NULL 值
- reactjs - 在 React 上重用组件
- javascript - can't use replaceAll or replace with nextjs/reactjs
- azure - 无法从 Azure Pipelines 将包下载到 Azure Artifacts
- security - Android - 在进入 RAM 之前加密变量
- c++ - C++20 概念和模板:固定大小和可调整大小的数组
- actions-on-google - 在 Google 地图中导航时调用操作:“此设备不支持 [操作名称]”
- prometheus - Alertmanager Send Resolved 到一个单独的通道
- r - 如何使用 setNodeSizeMapping 在 cytoscape RCy3 中映射节点大小
- python - 线图不绘图