React组件单选组选中后值无法更新问题排查
单选按钮状态不更新问题排查与解决
我开发了一个React组件,支持通过文本框输入文本,并从8个单选按钮中选择对应格式。使用useState实时管理状态变化,但无论选择哪个选项,返回的selectedStyle值始终为初始值"ama"。添加console.log(selectedStyle)跟踪状态,发现始终输出"ama";将RadioGroup的value={selectedStyle}改为defaultValue={selectedStyle}后,选中的单选按钮会高亮,但selectedStyle的值仍保持"ama"。
组件代码如下:
"use client" import { useState, useRef } from "react" import { Copy } from "lucide-react" import { Button } from "./ui/button" import { Textarea } from "./ui/textarea" import toTitleCase from "../lib/toTitleCase" import { Label } from "@/components/ui/label" import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group" import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "@/components/ui/tooltip" function TitleCaseInput() { const [value, setValue] = useState("") const [selectedStyle, setSelectedStyle] = useState("ama") const textareaRef = useRef<HTMLTextAreaElement>(null) const handleTextareaHover = () => { if (textareaRef.current && !textareaRef.current.disabled) { textareaRef.current.focus() } } const handleTextareaChange = ( event: React.ChangeEvent<HTMLTextAreaElement>, ) => { const input = event.target.value const output = toTitleCase(input, selectedStyle) setValue(output) } const handleCopyClick = () => { navigator.clipboard.writeText(value) } const styles = [ "AMA", "AP", "APA", "Bluebook", "Chicago", "MLA", "NYT", "Wikipedia", ] const styleTips = [ "American Medical Association Manual of Style", "The Associated Press Stylebook", "Publication Manual of the American Psychological Association", "The Bluebook: A Uniform System of Citation", "The Chicago Manual of Style", "The Modern Language Association Style Manual", "The New York Times Manual of Style and Usage", "Wikipedia: Manual of Style", ] // console.log(selectedStyle) return ( <div className="mx-2 flex flex-row gap-3 md:mx-4 md:last:mb-6 lg:mx-auto lg:max-w-full xl:max-w-8xl"> <div className="relative flex h-full flex-1 items-stretch md:flex-col"> <div className="relative flex flex-col w-full flex-grow p-4"> <div className="relative"> <Textarea ref={textareaRef} value={value} onChange={handleTextareaChange} onMouseEnter={handleTextareaHover} rows={1} maxRows={10} autoFocus placeholder="Your unformatted title..." className="resize-none pr-12 text-base py-3 scrollbar-thumb-blue scrollbar-thumb-rounded scrollbar-track-blue-lighter scrollbar-w-2 scrolling-touch" /> <Button className="absolute bottom-1.5 right-[8px]" variant="ghost" aria-label="convert" onClick={handleCopyClick} > <Copy className={`text-green-600 ${value ? "" : "text-gray-400"}`} /> </Button> </div> <h2 className="mb-3 mt-6 font-bold text-2xl">Style Guide</h2> <div> <TooltipProvider> <RadioGroup defaultValue="ama" value={selectedStyle} onChange={(event: React.ChangeEvent<HTMLInputElement>) => setSelectedStyle(event.target.value) } className="grid xs:grid-cols-2 sm:grid-cols-2 md:grid-cols-4 lg:grid-cols-8 gap-4" > {styles.map((style, index) => ( <div key={style} className="col-span-1 space-x-2"> <Tooltip> <RadioGroupItem value={style.toLowerCase()} id={`style${index + 1}`} /> <TooltipTrigger asChild> <Label htmlFor={`style${index + 1}`}>{style}</Label> </TooltipTrigger> <TooltipContent className="bg-gray-600 text-white"> <p>{styleTips[index]}</p> </TooltipContent> </Tooltip> </div> ))} </RadioGroup> </TooltipProvider> </div> </div> </div> </div> ) } export default TitleCaseInput
问题原因
shadcn/ui的RadioGroup组件的onChange回调参数并非React.ChangeEvent<HTMLInputElement>,而是直接返回选中的字符串值。你当前的代码试图访问event.target.value,但这里的event其实是选中的字符串,导致target属性不存在,代码执行出错,setSelectedStyle根本没有被调用,所以状态始终保持初始值。
解决方案
修改RadioGroup的onChange回调,直接接收选中的值作为参数:
<RadioGroup defaultValue="ama" value={selectedStyle} // 直接接收value参数,而非event对象 onChange={(value) => setSelectedStyle(value)} className="grid xs:grid-cols-2 sm:grid-cols-2 md:grid-cols-4 lg:grid-cols-8 gap-4" >
修改后,选择单选按钮时selectedStyle状态会正常更新,文本框也会根据选中的格式实时转换文本。
内容的提问来源于stack exchange,提问作者Ubiquitous Ubuntu
相关产品推荐
相关产品推荐

