提问人:in43sh 提问时间:10/21/2023 最后编辑:in43sh 更新时间:10/23/2023 访问量:67
useState 使动态样式应用较晚
useState makes dynamic styling apply late
问:
我正在开发Nextjs应用程序。这是我在客户端组件中的内容:
const [view, setView] = useState<string[]>(["all"]);
const story = stories?.holidays;
const joke = stories?.jokes;
const idiom = stories?.idioms;
const factoid = stories?.culturalTips;
const handleClick = (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
const target = e.currentTarget as HTMLButtonElement;
const value = target.innerText.toLowerCase();
setView((prevState) => {
if (value === "all") {
return ["all"];
} else {
// If any other filter is clicked while "all" is selected, deselect "all"
if (prevState.includes("all")) {
return [value];
} else {
// For other filters, toggle their selection status
if (prevState.includes(value)) {
const filteredView = prevState.filter(v => v !== value);
//Checks if no filter is selected, if so selects "all"
return filteredView.length === 0 ? ["all"] : filteredView;
} else {
return [...prevState, value];
}
}
}
});
};
return (
<Flex>
<Button
justifyContent={'center'}
backgroundColor={view.includes('all') ? 'gray.200' : 'orange.50'}
textColor={view.includes('all') ? 'black' : 'white'}
disabled={isLoading}
onClick={(e) => handleClick(e)}
>
<Text fontSize={'sm'}>All</Text>
</Button>
<Button
justifyContent={'center'}
backgroundColor={view.includes('story') ? 'gray.200' : 'orange.50'}
textColor={view.includes('story') ? 'black' : 'white'}
disabled={isLoading}
onClick={(e) => handleClick(e)}
>
// the rest of the buttons
</Flex>
{factoid &&
story &&
idiom &&
joke &&
(view.includes('all') || view.includes('story')) &&
story.map((holidayValue, idx) => (
<Box
border={'1px solid #E2E2E2'}
borderRadius={'10px'}
padding={'20px'}
my={'20px'}
boxShadow="lg"
key={idx}
>
<Image
width={40}
height={40}
className="stories-icon"
src={storyImg}
alt="story"
/>
<Text>{holidayValue}</Text>
</Box>
))}
// the same 3 more times for the joke, idiom, factoid
)
目标是能够同时应用多个过滤器。如果未应用任何筛选器,则选择“全部”。如果未应用任何筛选器,则按钮将变为原始状态。按钮样式是动态的,取决于视图状态。问题是它比应该的应用晚了一步。我认为这是因为 的异步性质,但我不知道如何解决它。我正在使用 Chakra UI,但我认为它不会引起任何问题。示例在下面的 GIF 上:useState
答:
1赞
tao
10/23/2023
#1
我建议任何时候都不要在活动过滤器数组中添加过滤器。筛选器(表示“所有项目”,又名“无筛选器”)是从 派生自 的状态。'all'
'all'
!activeFilters.length
下面是一个具有所需功能的组件(codesandbox 链接):
import * as React from 'react'
export const FilterButtons: React.FC<object> = () => {
const [activeFilters, setActiveFilters] = React.useState<string[]>([])
const filters = ['one', 'two', 'three', 'four']
const all = !activeFilters.length
const toggleFilter = (filter?: string) =>
setActiveFilters((prevState) =>
filter
? prevState.includes(filter)
? prevState.filter((f) => f !== filter)
: filters.length - prevState.length !== 1
? [...prevState, filter]
: []
: []
)
return (
<>
{filters.map((filter) => (
<button
key={filter}
onClick={() => toggleFilter(filter)}
className={activeFilters.includes(filter) ? 'active' : ''}
>
{filter}
</button>
))}
<button
className={all ? 'active' : ''}
onClick={() => toggleFilter()}
disabled={all}
>
all
</button>
</>
)
}
请注意,我使用的唯一状态是 ,因为其他任何变化都没有改变。activeFilters
如果里面的嵌套三元难以阅读,这里有一个更明确的版本:toggleFilter
function toggleFilter(filter?: string) {
setActiveFilters((prevState) => {
if (filter) {
if (prevState.includes(filter)) {
// remove filter
return prevState.filter((f) => f !== filter)
} else if (filters.length - prevState.length !== 1) {
// add filter
return [...prevState, filter]
}
}
// remove all filters
return []
})
}
评论
'all'
'all'
filters.length === activeFilters.length
disabled={isLoading}