在 React.js 中计算值的正确方法
Correct way to have calculated values in React.js
设置
所以基本上我有 3 个由状态支持的维度字段(长度、宽度和高度)。我想以英寸为单位保持状态,但允许用户随意切换显示器上的单位。目前我只支持英寸和英尺,所以我有一个“dimension_unit”状态来存储当前显示的单位,display_dimensions_multiplier 存储 1.0 英寸和 1.0/12.0 英尺(两者都处于状态) .除了一件事,我的一切都完全按照我的意愿工作。
问题
我尝试过的所有值都有效,除非您尝试使用小数。基本上,在后台它是 运行 抛出乘数以在更改时保存在状态中,然后乘回到字段的值中,这基本上擦除了尾随的“。”当您键入时,假设您正在尝试键入 4.5,您在键入时实际在字段中得到的是 45。但是如果您键入 45,然后将光标移动到 4 和 5 之间,添加 .你最终会得到 4.5...
我的想法
我考虑解决它的方法基本上是为 display_length 设置一个状态变量,然后设置常规长度状态,然后让 display_length 保持不变,除非它们更改单位并计算长度并在更改时存储,然后坚持下去……高度和宽度也一样……但这似乎非常不反应,那么这样做的反应方式是什么?或者是吗?
如果需要,很高兴 post 示例代码,但是任何组件都有很多代码,所以...是的...希望只是解释就足够了。
编辑1
fiddle之前的基本情况:before
这是我很好奇的想法:after
主要区别在于:
_handleChange: function(ev){
ev.stopPropagation()
ev.preventDefault()
var key = ev.target.name;
var value = ev.target.value;
var indims = this.state.input_dimensions;
indims[key] = value;
this.setState({input_dimensions: indims});
value = (value / this.state.display_dimensions_multiplier);
var dims = this.state.dimensions;
dims[key] = value;
this.setState({dimensions: dims});
},
我认为你的解决方案是正确的。几个类似的想法:
- 仅在提交输入时更新您的存储值(例如
onBlur
而不是 onChange
)。您可以应用通用实时输入验证来确保它是一个有效数字。
- 就像你说的那样使用一个单独的 "display" 状态(我会认为这是一个 "input state")并且当组件更新为新的存储值时,只更新不同的输入状态(当转换为相同的单位)。这样你就不需要坚持或担心输入组件之外的"input state"。
- 当输入有焦点时,存储值改变时不更新输入状态。当输入没有焦点或模糊时,将输入状态更新为存储值。
我不知道这些解决方案中的任何一个或您提出的解决方案比其他解决方案更 "Reacty"。我认为这真的取决于你。
设置
所以基本上我有 3 个由状态支持的维度字段(长度、宽度和高度)。我想以英寸为单位保持状态,但允许用户随意切换显示器上的单位。目前我只支持英寸和英尺,所以我有一个“dimension_unit”状态来存储当前显示的单位,display_dimensions_multiplier 存储 1.0 英寸和 1.0/12.0 英尺(两者都处于状态) .除了一件事,我的一切都完全按照我的意愿工作。
问题
我尝试过的所有值都有效,除非您尝试使用小数。基本上,在后台它是 运行 抛出乘数以在更改时保存在状态中,然后乘回到字段的值中,这基本上擦除了尾随的“。”当您键入时,假设您正在尝试键入 4.5,您在键入时实际在字段中得到的是 45。但是如果您键入 45,然后将光标移动到 4 和 5 之间,添加 .你最终会得到 4.5...
我的想法
我考虑解决它的方法基本上是为 display_length 设置一个状态变量,然后设置常规长度状态,然后让 display_length 保持不变,除非它们更改单位并计算长度并在更改时存储,然后坚持下去……高度和宽度也一样……但这似乎非常不反应,那么这样做的反应方式是什么?或者是吗?
如果需要,很高兴 post 示例代码,但是任何组件都有很多代码,所以...是的...希望只是解释就足够了。
编辑1
fiddle之前的基本情况:before
这是我很好奇的想法:after
主要区别在于:
_handleChange: function(ev){
ev.stopPropagation()
ev.preventDefault()
var key = ev.target.name;
var value = ev.target.value;
var indims = this.state.input_dimensions;
indims[key] = value;
this.setState({input_dimensions: indims});
value = (value / this.state.display_dimensions_multiplier);
var dims = this.state.dimensions;
dims[key] = value;
this.setState({dimensions: dims});
},
我认为你的解决方案是正确的。几个类似的想法:
- 仅在提交输入时更新您的存储值(例如
onBlur
而不是onChange
)。您可以应用通用实时输入验证来确保它是一个有效数字。 - 就像你说的那样使用一个单独的 "display" 状态(我会认为这是一个 "input state")并且当组件更新为新的存储值时,只更新不同的输入状态(当转换为相同的单位)。这样你就不需要坚持或担心输入组件之外的"input state"。
- 当输入有焦点时,存储值改变时不更新输入状态。当输入没有焦点或模糊时,将输入状态更新为存储值。
我不知道这些解决方案中的任何一个或您提出的解决方案比其他解决方案更 "Reacty"。我认为这真的取决于你。