如何延迟渲染Material-UI Select组件?升级后数据未就绪引发警告
I've run into this exact issue before—after upgrading Material-UI, the Select component gets stricter about ensuring the value prop matches one of the available MenuItem values. When your languages data is still loading, there are no MenuItems to match the value from localStorage, hence the warning. Here's how to fix it step by step:
1. Initialize State Properly
First, make sure your component's state initializes languages as an empty array instead of undefined. This avoids edge cases where the null check might behave unexpectedly:
constructor(props) { super(props); this.state = { languages: [] // Start with empty array, not undefined }; }
2. Replace Deprecated componentWillMount
componentWillMount is deprecated in React—switch to componentDidMount to fetch your data safely after the component mounts:
componentDidMount() { getLanguages.refetch({}).then(({ data }) => { if (data?.getLanguages) { this.setState({ languages: data.getLanguages }); } }); }
3. Guard Select Render Until Data is Ready
You have two solid options here to eliminate the warning:
Option A: Show Loading State Until Data Loads
Only render the full Select component once languages has data. This ensures there's always a matching MenuItem for your selected value:
// First, define a default language to avoid null from localStorage const currentLang = localStorage.getItem("lang") || "en"; {this.state.languages.length > 0 ? ( <FormControl> <InputLabel htmlFor="lang">{currentLang}</InputLabel> <Select value={currentLang} onChange={e => this.changeLng(e.target.value, i18n)} inputProps={{ name: "lang", id: "lang" }} > {this.state.languages.map((item, index) => ( <MenuItem key={index} value={item.value}> {item.name} </MenuItem> ))} </Select> </FormControl> ) : ( // Replace with your preferred loading indicator <CircularProgress size={24} /> )}
Option B: Keep Select Visible with Safe Fallback
If you need the Select to stay visible during loading, add a disabled loading MenuItem and disable the Select until data is ready:
const currentLang = localStorage.getItem("lang") || "en"; <FormControl> <InputLabel htmlFor="lang">{currentLang}</InputLabel> <Select value={this.state.languages.length > 0 ? currentLang : ""} onChange={e => this.changeLng(e.target.value, i18n)} inputProps={{ name: "lang", id: "lang" }} displayEmpty disabled={this.state.languages.length === 0} > {this.state.languages.length === 0 ? ( <MenuItem value="" disabled>Loading languages...</MenuItem> ) : ( this.state.languages.map((item, index) => ( <MenuItem key={index} value={item.value}> {item.name} </MenuItem> )) )} </Select> </FormControl>
Why This Works
Material-UI v4.x added stricter validation for the Select component: if the value prop doesn't match any MenuItem's value, it throws a warning. By ensuring we either wait to render the Select until data is available, or provide a valid fallback value/MenuItem during loading, we eliminate this mismatch.
内容的提问来源于stack exchange,提问作者NicoSan

