pra*_*ual 6 javascript forms reactjs
TLDR:在不违反React原则或忽略标准封装机会的情况下,React中的通用设计要求似乎是不可能的.
我有一个表单,显示来自服务器API的现有数据,并允许用户编辑字段并更新服务器上的数据.当用户更改输入值时,这会动态发生,而不是要求他们在每次编辑后"提交"表单.
对于某些表单输入,立即进行值更改(例如复选框,单选按钮,选择).对于其他人来说,价值变化是逐步增加的 - 最明显的是文本输入.我不希望每次击键都有服务器请求,因为这会导致为不完整的值生成服务器端验证错误.相反,一旦用户离开文本输入字段,服务器就会更新.如果值不变,发送服务器请求也是浪费.
在React中,关键的设计原则似乎是你保持一个真实/状态的单一来源,并通过使用道具的组件渗透.组件不应该保持自己的状态作为道具的副本,而是应该直接渲染道具[1]."单一来源"将是从服务器提取数据和向服务器提取数据的父组件.
对于渲染<input>元素,使其值与服务器更改保持同步,它应该使用value属性,因为defaultValue只在第一次渲染[2]上计算.React的设计原则意味着我应该设定<input value={this.props.value} />.为了响应用户输入,onChange还必须提供一个处理程序,将更改冒泡到父组件,这将更新状态并使<input>更新呈现props.
但是,我不想在onChange处理程序中触发服务器请求,因为这将在每次击键时触发.我需要在一个onBlur事件上触发服务器请求,假设该值已经改变了onFocus.对于某些元素而不是其他元素需要这个元素意味着父组件需要两个处理程序:一个onChange处理程序来更新所有子组件的状态并触发服务器对某些字段的请求,以及一个onBlur触发服务器请求其他字段.要求父组件知道哪些子表单组件应该表现出哪种行为似乎无法正确封装.子组件应该能够监视自己的值并决定何时发出"做某事"事件.
在没有违反React原则之一的情况下,我无法看到实现这一目标的方法,最有可能的方法是在每个表单组件中维护一个状态.像这样的东西:
class TextInput extends React.Component {
constructor(props) {
super(props);
this.initialValue = this.props.value;
this.setState({value: this.props.value});
}
componentWillReceiveProps = (nextProps) => {
this.initialValue = nextProps.value;
this.setState({value: nextProps.value});
};
handleFocus = (e) => {
this.initialValue = e.target.value;
};
handleChange = (e) => {
this.setState({value: e.target.value});
};
handleBlur = (e) => {
if (e.target.value !== this.initialValue &&
this.props.handleChange) {
this.props.handleChange(e);
}
};
render() {
return (
<input type="text"
value={this.state.value}
onFocus={this.handleFocus}
onChange={this.handleChange}
onBlur={this.handleBlur} />
);
}
}
class FormHandler extends React.Component {
componentDidMount() {
// fetch from API...
this.setState(apiResponse);
}
handleChange = (e) => {
// update API with e.target.value....
};
render() {
return (<TextInput value={this.state.value}
handleChange={this.handleChange} />);
}
}
Run Code Online (Sandbox Code Playgroud)
有没有更好的方法来实现这一目标,而不会破坏React的渲染道具的原则?
进一步阅读[3-4]中解决此问题的各种尝试.
其他SO问题来自于[5-6]中遇到类似问题的人们.
[1] https://facebook.github.io/react/tips/props-in-getInitialState-as-anti-pattern.html
[2] https://facebook.github.io/react/docs/forms.html#default-value
[3] https://discuss.reactjs.org/t/how-to-pass-in-initial-value-to-form-fields/869
[4] https://blog.iansinnott.com/managing-state-and-controlled-form-fields-with-react/
您显然花了很多时间思考这个问题并查找相关讨论。对于它的价值,我认为你实际上是在过度思考这个问题。React 的核心是一个非常实用的工具。它会将您推向某些方向,并且肯定有一些方法被认为是惯用的,但它提供了许多逃生舱口,允许您突破基本方法以适应您的特定用例。因此,如果您需要以一种特定的方式构建事物以使您的应用程序按照您想要的方式运行,请不要花时间担心它是否“绝对完全符合 React 的原则”。没有人会因为你偏离某些神话般的理想而对你大喊大叫:)
是的,您提供的示例代码乍一看似乎非常合理。
| 归档时间: |
|
| 查看次数: |
2276 次 |
| 最近记录: |