React中MUI Chip组件首次点击不渲染问题求助
问题解决:点击Add按钮后MUI Chip不立即显示的问题
问题原因
核心问题是状态更新未触发React重新渲染。在addWithSuffix函数中,你直接复用了原finalValue数组的引用(tempArray = finalValue只是复制引用而非创建新数组),随后将同一个引用传给setFinalValue。React通过对比状态引用判断是否需要更新,引用未变化时不会触发组件重渲染,因此Chip不会立即显示。只有修改Name或Suffix触发value状态更新时,组件才会重新渲染,此时新添加的Chip才会出现。
修复方案
修改addWithSuffix函数,通过创建新数组来更新状态,避免直接修改原数组:
const addWithSuffix = () => { const newItem = `${value.adnCharge} (${value.desgnSuffix})`; // 使用函数式更新确保拿到最新状态,同时创建新数组 setFinalValue(prevFinalValue => [...prevFinalValue, newItem]); }
也可以用concat方法创建新数组:
const addWithSuffix = () => { const newItem = `${value.adnCharge} (${value.desgnSuffix})`; setFinalValue(finalValue.concat(newItem)); }
修改后的完整代码
import { useState } from 'react'; import styled from 'styled-components'; import {OutlinedInput, MenuItem, Chip, useTheme, Select} from '@mui/material'; const ITEM_HEIGHT = 48; const ITEM_PADDING_TOP = 8; const MenuProps = { PaperProps: { style: { maxHeight: ITEM_HEIGHT * 4.5 + ITEM_PADDING_TOP, width: 250, }, }, }; const EditUser =styled.div` display: flex; align-items: center; justify-content: flex-start; margin-left:5px; margin-top: 10px; margin-bottom: 20px; ` const Label = styled.label` width: 100px; margin: 10px; ` const LabelInputWrapper = styled.div` margin-bottom:25px; flex:1 0 30%; display: ${(props) => props.disp}; ` const Adduserformcont = styled.div` display: flex; flex-wrap:wrap; margin:10px; ` const AddChrgWrapper = styled.div` display: flex; ` const names = [ 'Oliver Hansen', 'Van Henry', 'April Tucker', 'Ralph Hubbard', 'Omar Alexander', 'Carlos Abbott', 'Miriam Wagner', 'Bradley Wilkerson', 'Virginia Andrews', 'Kelly Snyder', ]; function getStyles(name, personName, theme) { return { fontWeight: personName.indexOf(name) === -1 ? theme.typography.fontWeightRegular : theme.typography.fontWeightMedium, }; } const desigSuffix = ["I","II", "III", "IV"]; const EditUsers = () => { const theme = useTheme(); const [personName, setPersonName] = useState([]); const [value, setValue] = useState({}) const [finalValue, setFinalValue] =useState([]) const onChangeUserForm = (event) => { if(event.target.name === 'selectMultiAddnCharg'){ setPersonName(event.target.value) } let temp = {...value, [event.target.name]:event.target.value} setValue(temp); } // 修复后的添加函数 const addWithSuffix = () => { const newItem = `${value.adnCharge} (${value.desgnSuffix})`; setFinalValue(prevFinalValue => [...prevFinalValue, newItem]); } return ( <> <form> <AddChrgWrapper> <Label>Select name</Label> <Select name='selectMultiAddnCharg' multiple displayEmpty value={personName} onChange={onChangeUserForm} input={<OutlinedInput />} renderValue={(selected) => { if (selected.length === 0) { return <em>Select name</em>; } return selected.join(', '); }} MenuProps={MenuProps} inputProps={{ 'aria-label': 'Without label' }} > <MenuItem disabled value=""> <em>Placeholder</em> </MenuItem> {names.map((name) => ( <MenuItem key={name} value={name} style={getStyles(name, personName, theme)} > {name} </MenuItem> ))} </Select> </AddChrgWrapper> <LabelInputWrapper name="adnCharge"> <Label>Name</Label> <select name="adnCharge" onChange={onChangeUserForm}> <option>Select</option> {personName.map((item,index) => <option key={index}>{item}</option>)} </select> </LabelInputWrapper> <LabelInputWrapper name="desgnSuffix" > <Label>Suffix</Label> <select name="desgnSuffix" onChange={onChangeUserForm}> <option>Select</option> {desigSuffix.map((item,index) => <option key={index}>{item}</option>)} </select> </LabelInputWrapper> <button type="button" onClick={addWithSuffix}>Add</button> <div>{finalValue.map((item, index)=><Chip key={index} label={item}/>)}</div> </form> </> ) } export default EditUsers
额外说明
使用函数式更新(setFinalValue(prevFinalValue => [...prevFinalValue, newItem]))是更稳妥的写法,它能确保你获取到最新的状态值,避免因React状态更新的异步特性导致的逻辑错误。
内容的提问来源于stack exchange,提问作者New Coder
相关产品推荐
相关产品推荐

