gpt4 book ai didi

javascript - React getDerivedStateFromProps() 的使用

转载 作者:行者123 更新时间:2023-11-30 19:11:02 24 4
gpt4 key购买 nike

我正在探索 React,但对生命周期方法和父子通信有些困惑。具体来说,我正在尝试创建一个组件,它包装一个选择元素并在选择“其他”选项时添加一个输入框。我已经使用 getDerivedStateFromProps() 实现了这个,但是根据 documentation应该很少使用此生命周期方法。因此我的问题是:在这种情况下,我应该了解并使用另一种模式吗?

这是我的代码,值和选项作为 Prop 传递下来,父组件的 handleChange() 方法也是如此。因此,当在 select 或 input 元素中进行更改时,首先更新父组件状态,并通过 props.value 向下传递新值。

export default class SelectOther extends Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
}

static getDerivedStateFromProps(props) {
let optionIndex = -1;
for (let i = 0; i < props.options.length; i++) {
if (props.options[i].value === props.value) {
optionIndex = i;
break;
}
}
if (optionIndex > -1) {
return {
selected: props.options[optionIndex].value,
text: "",
showInput: false
};
} else {
return {
selected: "",
text: props.value,
showInput: true
};
}
}

handleChange(e) {
this.props.handleChange({
"target": {
"name": this.props.name,
"value": e.target.value
}
});
}

render() {
return (
<div>
<label>{ this.props.label }</label>
<select name={ this.props.name } value={ this.state.selected } onChange={ this.handleChange }>
{
this.props.options.map(option => <option key={option.value} value={option.value}>{option.label}</option>)
}
<option value="">Other</option>
</select>
{
this.state.showInput &&
<div>
<label>{ this.props.label } (specify other)</label>
<input type="text" className="form-control" value={ this.state.text } onChange={ this.handleChange }></input>
</div>
}
</div>
)
}
}

最佳答案

您可以通过不让 SelectOther 具有任何状态来简化,这里是一个示例,说明您如何传递一个函数来分派(dispatch)一个操作来更改值。因为 SelectOther 是一个纯组件,所以它不会不必要地重新渲染:

//make this a pure component so it won't re render
const SelectOther = React.memo(function SelectOther({
label,
name,
value,
options,
handleChange,
}) {
console.log('in render',name, value);
const showInput = !options
.map(o => o.value)
.includes(value);
return (
<div>
<label>{label}</label>
<select
name={name}
value={showInput ? '' : value}
onChange={handleChange}
>
{options.map(option => (
<option key={option.value} value={option.value}>
{option.label}
</option>
))}
<option value="">Other</option>
</select>
{showInput && (
<div>
<label>{label} (specify other)</label>
<input
type="text"
name={name}
className="form-control"
value={value}
onChange={handleChange}
></input>
</div>
)}
</div>
);
});

const App = () => {
//create options once during App life cycle
const options = React.useMemo(
() => [
{ value: 'one', label: 'one label' },
{ value: 'two', label: 'two label' },
],
[]
);
//create a state to hold input values and provide
// a reducer to create new state based on actions
const [state, dispatch] = React.useReducer(
(state, { type, payload }) => {
//if type of action is change then change the
// payload.name field to payload.value
if (type === 'CHANGE') {
const { name, value } = payload;
return { ...state, [name]: value };
}
return state;
},
//initial state for the inputs
{
my_name: '',
other_input: options[0].value,
}
);
//use React.useCallback to create a callback
// function that doesn't change. This would be
// harder if you used useState instead of useReducer
const handleChange = React.useCallback(
({ target: { name, value } }) => {
dispatch({
type: 'CHANGE',
payload: {
name,
value,
},
});
},
[]
);
return (
<div>
<SelectOther
label="label"
name="my_name"
value={state.my_name}
options={options}
handleChange={handleChange}
/>
<SelectOther
label="other"
name="other_input"
value={state.other_input}
options={options}
handleChange={handleChange}
/>
</div>
);
};


//render app
ReactDOM.render(
<App />,
document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>

我本可以在 App 中使用 useState 但我必须使用 useEventCallback或者为每个输入值做一个 useState。 following documentation提出了 useEventCallback 模式,然后在声明我们不推荐这种模式之后立即提出,这就是我提出 useReducer 解决方案的原因。

关于javascript - React getDerivedStateFromProps() 的使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58473011/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com