React - 通过传递props更改输入defaultValue

时间:2015-06-09 09:15:19

标签: javascript forms reactjs default-value

考虑这个例子:

var Field = React.createClass({
    render: function () {
        // never renders new value...
        return (
            <div>
                <input type="text" defaultValue={this.props.value || ''} />
            </div>
        );
    }
});

var App = React.createClass({
    getInitialState: function () {
        return {value: 'Hello!'};
    },

    changeTo: function (str) {
        this.setState({value: str});
    },

    render: function () {
        return (
            <div>
                <Field value={this.state.value} />
                <button onClick={this.changeTo.bind(null, 'Whyyyy?')}>Change to "Whyyyy?"</button>
                <button onClick={this.changeTo.bind(null, void 0)}>Change to undefined</button>
            </div>
        );
    }
});

React.render(
    <App />,
    document.getElementById('app')
);

我想将值传递给defaultValue作为哑输入组件的支柱。然而,它永远不会重新呈现它。

7 个答案:

答案 0 :(得分:46)

如上所述,defaultValue仅在表单的初始加载时设置。在那之后,它不会自然而然地#34;更新,因为意图只是设置初始默认值。

如果需要,可以通过将key传递给包装器组件来解决此问题,例如在FieldApp组件上,尽管在更实际的情况下,它可能会是一个form组件。好的key将是传递给表单的资源的唯一值 - 例如,存储在数据库中的id。

在简化的情况下,您可以在Field渲染中执行此操作:

<div key={this.props.value}>
    <input type="text" defaultValue={this.props.value || ''} />
</div>

在一个更复杂的表格案例中,像这样的东西可能会得到你想要的东西,例如你的onSubmit动作提交给API但是停留在同一页面上:

const Form = ({item, onSubmit}) => {
  return (
    <form onSubmit={onSubmit} key={item.id}>
      <label>
        First Name
        <input type="text" name="firstName" defaultValue={item.firstName} />
      </label>
      <label>
        Last Name
        <input type="text" name="lastName" defaultValue={item.lastName} />
      </label>
      <button>Submit!</button>
    </form>
  )
}

Form.defaultProps = {
  item: {}
}

Form.propTypes = {
  item: PropTypes.object,
  onSubmit: PropTypes.func.isRequired
}

当使用不受控制的表单输入时,我们通常不会关注这些值,直到它们被提交为止,这就是为什么当你真正强制重新渲染它时更为理想的原因想要更新defaultValues(提交后,而不是每次更改单个输入)。

如果您还要编辑相同的表单并担心API响应可能会返回不同的值,则可以提供ID和时间戳之类的组合键。

答案 1 :(得分:12)

defaultValue 仅适用于初始加载。在那之后,它不会得到更新。您需要为 Field 组件维护状态:

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 (
            <div>
                <input type="text" onChange={this._handleChange} 
                                   value={this.state.value || ''} />
            </div>
        );
    }
});

答案 2 :(得分:4)

我相当肯定这与Controlled vs. Uncontrolled inputs有关。

如果我理解正确,由于您的<input>不受控制(没有定义value属性),因此该值将始终解析为初始化的值。在这种情况下Hello!

为了解决此问题,您可以添加value属性并在onChange期间设置它:

var Field = React.createClass({
      render: function () {
          // never renders new value...
          return (
              <div>
                  <input type="text" defaultValue={this.props.default || ''} value={this.props.value} />
              </div>
          );
      }
  });

Here is a plunker显示更改。

答案 3 :(得分:0)

我也遇到了这个问题,我所做的是在道具发生变化时手动更新输入值。将其添加到Field反应类:

componentWillReceiveProps(nextProps){
    if(nextProps.value != this.props.value) {
        document.getElementById(<element_id>).value = nextProps.value
    }
}

您只需要在元素中添加一个id属性,以便找到它。

答案 4 :(得分:0)

问题在于:

onClick={this.changeTo.bind(null, 'Whyyyy?')}

我很好奇为什么要绑定null。

您想要绑定到'this',以便changeTo将在此对象中设置State。

试试这个

<button onClick={this.changeTo.bind(this, 'Whyyyy?')}>Change to "Whyyyy?"</button>
<button onClick={this.changeTo.bind(this, void 0)}>Change to undefined</button>

在Javascript中,当一个函数被调用时,它在调用它的范围内被调用,而不是它被写入的位置(我知道,似乎反直觉)。为了确保在你编写它的上下文中调用它,你需要'.bind(this)'。

要了解有关绑定和功能范围的更多信息,有很多在线设备(有些比其他设备好得多) - 您可能会喜欢这个:http://ryanmorr.com/understanding-scope-and-context-in-javascript/

如果您使用的是firefox或chrome,我还建议您使用React Dev工具,这样您就可以看到state.message没有改变: https://facebook.github.io/react/blog/2015/09/02/new-react-developer-tools.html

答案 5 :(得分:0)

使用条件渲染,然后组件将加载正确的初始值。像这个模块中的东西:

class MenuHeaderInput extends React.Component{
    constructor(props){
        super(props);
        this.handleBlur = this.handleBlur.bind (this);
    }
    handleBlur (e) {
        this.props.menuHeaderUpdate(e.target.value);
    }
    render(){
        if (this.props.menuHeader) {
            return (
                <div className="w3-row w3-margin" onClick = {() => this.props.handleTitleClick (10)}>
                    <div className="w3-third" ><pre></pre></div>
                    <input
                        className = {"w3-third w3-input w3-jumbo " + EDIT_COLOR}                
                        type = "text"
                        defaultValue = {this.props.menuHeader}
                        onBlur = {this.handleBlur}
                    />
                    <div className="w3-third" ><pre></pre></div>                
                </div>
            )
        }
        else {
            return null;
        }
    }
}

答案 6 :(得分:0)

您可以有条件地进行输入,然后每次要强制更新defaultValue时,只需要卸载输入,然后立即再次渲染。