Javascript React - 通过传递道具更改输入默认值

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30727837/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 05:39:50  来源:igfitidea点击:

React - change input defaultValue by passing props

javascriptformsreactjsdefault-value

提问by Kosmetika

Consider this example:

考虑这个例子:

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')
);

I want to pass value into defaultValueas prop of dumb input component. However it never re-renders it.

我想将值defaultValue作为哑输入组件的道具传递。但是它永远不会重新渲染它。

回答by Sia

As a previous answer mentioned, defaultValueonly gets set on initial load for a form. After that, it won't get "naturally" updated because the intent was only to set an initial default value.

正如前面提到的答案,defaultValue仅在表单的初始加载时设置。之后,它不会“自然”更新,因为目的只是设置初始默认值。

You can get around this if you need to by passing a keyto the wrapper component, like on your Fieldor Appcomponent, though in more practical circumstances, it would probably be a formcomponent. A good keywould be a unique value for the resource being passed to the form - like the id stored in the database, for example.

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

In your simplified case, you could do this in your Field render:

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

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

In a more complex form case, something like this might get what you want if for example, your onSubmit action submitted to an API but stayed on the same page:

在更复杂的表单案例中,例如,如果您的 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
}

When using uncontrolled form inputs, we generally don't care about the values until after they are submitted, so that's why it's more ideal to only force a re-render when you really want to update the defaultValues (after submit, not on every change of the individual input).

当使用不受控制的表单输入时,我们通常在提交之后才关心这些值,所以这就是为什么只在您真正想要更新 defaultValues 时才强制重新渲染更为理想(提交之后,而不是每次更改时)个人输入)。

If you're also editing the same form and fear the API response could come back with different values, you could provide a combined key of something like id plus timestamp.

如果您还在编辑相同的表单并且担心 API 响应可能会返回不同的值,您可以提供一个组合键,如 id 加时间戳。

回答by drogon

defaultValueonly works for the initial load. After that, it won't get updated. You need to maintain the state for you Fieldcomponent:

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>
        );
    }
});

回答by Davin Tryon

I'm fairly certain this has to do with Controlled vs. Uncontrolled inputs.

我相当肯定这与Controlled vs. Uncontrolled 输入有关

If I understand correctly, since your <input>is Uncontrolled (doesn't define a valueattribute), then the value will always resolve to the value that it is initialized with. In this case Hello!.

如果我理解正确,因为您<input>是不受控制的(未定义value属性),那么该值将始终解析为初始化时使用的值。在这种情况下Hello!

In order to overcome this issue, you can add a valueattribute and set it during the onChange:

为了克服这个问题,您可以添加一个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 plunkershowing the change.

这是一个显示更改的plunker

回答by Kael Vergara

I also face this problem, what I did was to manually update the input value when the props has change. Add this to your Field react class:

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

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

You just need to add an id attribute to your element so that it can be located.

您只需要向您的元素添加一个 id 属性,以便可以定位它。

回答by Frazer Kirkman

The issue is here:

问题在这里:

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

I'm curious why you bind to null.

我很好奇你为什么绑定到 null。

You want to bind to 'this', so that changeTo will setState in THIS object.

您想绑定到“this”,以便 changeTo 将在 THIS 对象中设置状态。

Try this

尝试这个

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

In Javascript, when a function is called, its called in the scope where it was called from, not where it was written (I know, seems counter intuitive). To ensure it is called in the context you write it, you need to '.bind(this)'.

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

To learn more about binding and function scope, there are lots of online tutes, (some much better than others) - you might like this one: http://ryanmorr.com/understanding-scope-and-context-in-javascript/

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

I also recommend using the React Dev tools if you are using firefox or chrome, this way you would have been able to see that state.message was not changing: https://facebook.github.io/react/blog/2015/09/02/new-react-developer-tools.html

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

回答by Kaj Risberg

Use conditional rendering, then the component will load correct initial value. Something like in this module:

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

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;
        }
    }
}

回答by Bnaya Zil

You can make the input conditionally and then every time you want to force an update of the defaultValueyou just need to unmount the input and then immediately render it again.

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