React.js中switch case始终执行default分支问题求助
问题分析与解决方案
问题现象
使用<select>结合useContext()实现组件间状态更新时,尽管console.log(ev.target.name)输出的值与switch的case完全匹配,但switch始终执行default分支,控制台会同时打印出对应的属性名和"attribute wasn't successfully changed"。
相关代码片段
渲染Select组件的代码
const selectNames = [ "Strength", "Dexterity", "Constitution", "Intelligence", "Wisdom", "Charisma" ] const options = [ { label: '16', value: '16' }, { label: '14', value: '14-1' }, { label: '14', value: '14-2' }, { label: '12', value: '12-1' }, { label: '12', value: '12-2' }, { label: '10', value: '10' } ] const selectRender = selectNames.map((name, index) => { return ( <> <label for={name}>{name}:</label> <select name={name} key={index} onChange={handleChange} value={chosenOptions[name] || ''} required={index === 0} id={name.toLowerCase()}> <option value=''></option> {options.filter(({value}) => !isChosenByOther(value, name)) .map(({label, value}, oIndex) => <option value={value} key={oIndex}>{label}</option>) } </select> </> ) })
事件处理函数代码
const handleChange = (ev) => { setChosenOptions({...chosenOptions, [ev.target.name]: ev.target.value}); console.log(ev.target.name) switch (ev.target.name) { case "Strength": setStrength(ev.target.value) case "Dexterity": setDexterity(ev.target.value) case "Constitution": setConstitution(ev.target.value) case "Intelligence": setIntelligence(ev.target.value) case "Wisdom": setWisdom(ev.target.value) case "Charisma": setCharisma(ev.target.value) default: console.log("attribute wasn't successfully changed") } };
控制台输出
Intelligence attribute wasn't successfully changed Charisma attribute wasn't successfully changed Wisdom attribute wasn't successfully changed
问题原因
你的switch语句中所有case分支都没有添加break关键字。JavaScript的switch会在匹配到第一个符合条件的case后,继续执行后续所有case和default的代码,直到遇到break或代码块结束。所以即使匹配到了对应的属性分支,代码会一路执行到default,导致你看到的现象。
修复方案
方案1:添加break关键字
给每个case分支末尾添加break,终止当前分支的执行:
const handleChange = (ev) => { setChosenOptions({...chosenOptions, [ev.target.name]: ev.target.value}); console.log(ev.target.name) switch (ev.target.name) { case "Strength": setStrength(ev.target.value) break; case "Dexterity": setDexterity(ev.target.value) break; case "Constitution": setConstitution(ev.target.value) break; case "Intelligence": setIntelligence(ev.target.value) break; case "Wisdom": setWisdom(ev.target.value) break; case "Charisma": setCharisma(ev.target.value) break; default: console.log("attribute wasn't successfully changed") } };
方案2:用对象映射替代switch
这种方式代码更简洁,也避免了break遗漏的问题:
const handleChange = (ev) => { const { name, value } = ev.target; setChosenOptions({...chosenOptions, [name]: value}); console.log(name); const setterMap = { Strength: setStrength, Dexterity: setDexterity, Constitution: setConstitution, Intelligence: setIntelligence, Wisdom: setWisdom, Charisma: setCharisma }; if (setterMap[name]) { setterMap[name](value); } else { console.log("attribute wasn't successfully changed"); } };
内容的提问来源于stack exchange,提问作者GoldenBadger
相关产品推荐
相关产品推荐

