React - 通过传递属性更改输入框的默认值
React - 通过传递属性更改输入框的默认值
考虑这个例子:
var Field = React.createClass({ render: function () { // 永远不会重新渲染新值... return ( ); } }); var App = React.createClass({ getInitialState: function () { return {value: 'Hello!'}; }, changeTo: function (str) { this.setState({value: str}); }, render: function () { return (); } }); React.render( , document.getElementById('app') );
我想将值作为无状态输入组件的prop传递给defaultValue
。然而它从不重新渲染它。
React - 通过传递props更改输入框的defaultValue问题的出现原因是defaultValue只在初始加载时起作用,之后不会被更新。为了解决这个问题,需要在Field组件中维护一个状态来保存输入框的值。解决方法是在Field组件中使用getInitialState函数将props的值转移到状态中,并在componentWillReceiveProps生命周期函数中更新状态。同时,使用_handleChange函数来处理输入框值的变化,并将最新的值保存在状态中,最后通过value属性将状态中的值绑定到输入框上以实现更新。整体代码如下:
var Field = React.createClass({ //transfer props to state on load getInitialState: function () { return {value: this.props.value}; }, //if the parent component updates the prop, force re-render componentWillReceiveProps: function(nextProps) { this.setState({value: nextProps.value}); }, //re-render when input changes _handleChange: function (e){ this.setState({value: e.target.value}); }, render: function () { // render based on state return (); } });
以上就是React - 通过传递props更改输入框的defaultValue问题的出现原因及解决方法。使用以上代码,可以实现通过传递props来改变输入框的默认值,并保持输入框的值随着props的更新而更新。
React - 通过传递props更改输入框的默认值
在这个问题中,出现的原因与受控组件和非受控组件有关。如果我理解正确的话,由于您的是非受控的(没有定义value属性),所以值将始终解析为初始化时的值。在这种情况下是"Hello!"。
为了解决这个问题,您可以添加一个value属性,并在onChange事件中设置它:
var Field = React.createClass({ render: function () { // never renders new value... return (); } });
这里有一个展示了这个变化的plunker。
这是解决非受控组件的最简洁的方法吗?另外,我在您的示例中没有看到任何onChange函数。
非受控组件不需要onChange。通常,可以使用ref来提取值。
太棒了,关于设置value和其他键(如onKeyUp / onKeyPress)存在一个bug,所以如果您需要使用onKeyUp等事件,您应该在同一个函数中设置onChange,否则value属性将不会更新。
React中,通过传递props来改变input的defaultValue的问题是defaultValue只会在表单初始加载时设置。之后,它不会被“自然”更新,因为它只是用于设置初始默认值的意图。如果需要解决这个问题,可以通过在包装组件(如Field或App组件,或者更实际的情况下,是一个form组件)上传递一个key来绕过这个问题。一个好的key可以是传递给表单的资源的唯一值,比如数据库中存储的id。在简化的情况下,可以在Field的render方法中这样做:
在更复杂的表单情况下,如果例如提交的onSubmit操作提交到一个API但仍然停留在同一页上,可以使用以下代码来实现期望的效果:
const Form = ({item, onSubmit}) => { return () } Form.defaultProps = { item: {} } Form.propTypes = { item: PropTypes.object, onSubmit: PropTypes.func.isRequired }
当使用不受控的表单输入时,我们通常只关心值在提交后是否发生了变化,因此最理想的情况是只在真正想要更新默认值时强制重新渲染(在提交后,而不是在每次单个输入更改时)。如果还在同一个表单上进行编辑,并且担心API响应可能会返回不同的值,可以使用id加上时间戳这样的组合key。
将值用作key只是一种hack方法,它会根据值的更改次数多次挂载元素。虽然它可以解决问题,但它不是更新输入值的最佳方式。实际上,它并不更新值,而是创建一个新值(在极端情况下可能导致内存泄漏)。最好使用受控输入字段而不是这种解决方案。
另外,对于多个值,可以使用key={[props.values.a, props.values.b]}来解决问题。你认为这样做会有性能影响吗?