我正在尝试使用react创建一个简单的表单,但是在数据正确绑定到表单的defaultValue时遇到困难。
我正在寻找的行为是:
但是,现在,我发现每次刷新页面时Text输入字段都是空白的。 (虽然我在输入中键入的内容确实保存并保持不变。)我认为这是因为输入文本字段的html在AwayMessage为空对象时加载,但在farMessage加载时不刷新。此外,我无法为该字段指定默认值。
为清晰起见,我删除了一些代码(即onToggleChange)
window.Pages ||= {}
Pages.AwayMessages = React.createClass
getInitialState: ->
App.API.fetchAwayMessage (data) =>
@setState awayMessage:data.away_message
{awayMessage: {}}
onTextChange: (event) ->
console.log "VALUE", event.target.value
onSubmit: (e) ->
window.a = @
e.preventDefault()
awayMessage = {}
awayMessage["master_toggle"]=@refs["master_toggle"].getDOMNode().checked
console.log "value of text", @refs["text"].getDOMNode().value
awayMessage["text"]=@refs["text"].getDOMNode().value
@awayMessage(awayMessage)
awayMessage: (awayMessage)->
console.log "I'm saving", awayMessage
App.API.saveAwayMessage awayMessage, (data) =>
if data.status == 'ok'
App.modal.closeModal()
notificationActions.notify("Away Message saved.")
@setState awayMessage:awayMessage
render: ->
console.log "AWAY_MESSAGE", this.state.awayMessage
awayMessageText = if this.state.awayMessage then this.state.awayMessage.text else "Placeholder Text"
`<div className="away-messages">
<div className="header">
<h4>Away Messages</h4>
</div>
<div className="content">
<div className="input-group">
<label for="master_toggle">On?</label>
<input ref="master_toggle" type="checkbox" onChange={this.onToggleChange} defaultChecked={this.state.awayMessage.master_toggle} />
</div>
<div className="input-group">
<label for="text">Text</label>
<input ref="text" onChange={this.onTextChange} defaultValue={awayMessageText} />
</div>
</div>
<div className="footer">
<button className="button2" onClick={this.close}>Close</button>
<button className="button1" onClick={this.onSubmit}>Save</button>
</div>
</div>
我的AwayMessage的console.log显示以下内容:
AWAY_MESSAGE Object {}
AWAY_MESSAGE Object {id: 1, company_id: 1, text: "Sample Text", master_toggle: false}
答案 0 :(得分:57)
如果要初始化输入,则应使用defaultValue,但如果要使用state更改值,则需要使用value。我个人喜欢使用defaultValue,如果我只是初始化它,然后只需使用refs来获取我提交的值。有关反应文档的参考和输入的更多信息,https://facebook.github.io/react/docs/forms.html和https://facebook.github.io/react/docs/working-with-the-browser.html。
这是我如何重写你的输入:
awayMessageText = if this.state.awayMessage then this.state.awayMessage.text else ''
<input ref="text" onChange={this.onTextChange} placeholder="Placeholder Text" value={@state.awayMessageText} />
此外,您不想像往常一样传递占位符文字,因为这实际上会将值设置为“占位符文字”。您仍然需要将空值传递给输入,因为undefined和nil基本上将值转换为defaultValue。 https://facebook.github.io/react/tips/controlled-input-null-value.html
运行getInitialState后需要进行api调用。对于您的情况,我会在componentDidMount中执行此操作。请遵循此示例https://facebook.github.io/react/tips/initial-ajax.html。
我还建议您阅读组件生命周期并做出反应。 https://facebook.github.io/react/docs/component-specs.html
就我个人而言,我不喜欢做整个渲染中的其他逻辑而更喜欢使用“加载”#39;在我的状态下,在表单加载http://fortawesome.github.io/Font-Awesome/examples/之前渲染一个字体真棒微调器。这是一个重写,向您展示我的意思。如果我弄乱了cjsx的滴答声,那是因为我通常只是像这样使用coffeescript,。
window.Pages ||= {}
Pages.AwayMessages = React.createClass
getInitialState: ->
{ loading: true, awayMessage: {} }
componentDidMount: ->
App.API.fetchAwayMessage (data) =>
@setState awayMessage:data.away_message, loading: false
onToggleCheckbox: (event)->
@state.awayMessage.master_toggle = event.target.checked
@setState(awayMessage: @state.awayMessage)
onTextChange: (event) ->
@state.awayMessage.text = event.target.value
@setState(awayMessage: @state.awayMessage)
onSubmit: (e) ->
# Not sure what this is for. I'd be careful using globals like this
window.a = @
@submitAwayMessage(@state.awayMessage)
submitAwayMessage: (awayMessage)->
console.log "I'm saving", awayMessage
App.API.saveAwayMessage awayMessage, (data) =>
if data.status == 'ok'
App.modal.closeModal()
notificationActions.notify("Away Message saved.")
@setState awayMessage:awayMessage
render: ->
if this.state.loading
`<i className="fa fa-spinner fa-spin"></i>`
else
`<div className="away-messages">
<div className="header">
<h4>Away Messages</h4>
</div>
<div className="content">
<div className="input-group">
<label for="master_toggle">On?</label>
<input type="checkbox" onChange={this.onToggleCheckbox} checked={this.state.awayMessage.master_toggle} />
</div>
<div className="input-group">
<label for="text">Text</label>
<input ref="text" onChange={this.onTextChange} value={this.state.awayMessage.text} />
</div>
</div>
<div className="footer">
<button className="button2" onClick={this.close}>Close</button>
<button className="button1" onClick={this.onSubmit}>Save</button>
</div>
</div>
应该覆盖它。现在,这是使用状态和值的表单的一种方法。您也可以使用defaultValue而不是value,然后使用refs在提交时获取值。如果你走这条路线,我建议你有一个外壳组件(通常称为高阶组件)来获取数据,然后将它作为道具传递给表单。
总的来说,我建议一直阅读反应文档并做一些教程。那里有很多博客,http://www.egghead.io有一些很好的教程。我的网站上也有一些东西,http://www.openmindedinnovations.com。
答案 1 :(得分:47)
解决此问题的另一种方法是更改输入的key
。
<input ref="text" key={this.state.awayMessage ? 'notLoadedYet' : 'loaded'} onChange={this.onTextChange} defaultValue={awayMessageText} />
更新:
由于这会得到提升,我将不得不说,在内容加载时你应该正确地拥有disabled
或readonly
道具,这样你就不会减少ux体验。
是的,它很可能是一个黑客,但它完成了工作......; - )
答案 2 :(得分:2)
也许不是最好的解决方案,但我制作了类似下面的组件,因此我可以在代码中的任何地方重复使用它。我希望它默认已经做出反应。
<MagicInput type="text" binding={[this, 'awayMessage.text']} />
该组件可能如下所示:
window.MagicInput = React.createClass
onChange: (e) ->
state = @props.binding[0].state
changeByArray state, @path(), e.target.value
@props.binding[0].setState state
path: ->
@props.binding[1].split('.')
getValue: ->
value = @props.binding[0].state
path = @path()
i = 0
while i < path.length
value = value[path[i]]
i++
value
render: ->
type = if @props.type then @props.type else 'input'
parent_state = @props.binding[0]
`<input
type={type}
onChange={this.onChange}
value={this.getValue()}
/>`
其中,按数组更改是通过数组表示的路径访问哈希的函数
changeByArray = (hash, array, newValue, idx) ->
idx = if _.isUndefined(idx) then 0 else idx
if idx == array.length - 1
hash[array[idx]] = newValue
else
changeByArray hash[array[idx]], array, newValue, ++idx
答案 3 :(得分:2)
要强制 defaultValue 重新渲染,您需要做的就是更改输入本身的键值。这是你的方法。
<input
type="text"
key={myDynamicKey}
defaultValue={myDynamicDefaultValue}
placeholder="It works"/>
答案 4 :(得分:1)
设置初始值的最可靠方法是使用componentDidMount(){}以及render(){}:
...
componentDidMount(){
const {nameFirst, nameSecond, checkedStatus} = this.props;
document.querySelector('.nameFirst').value = nameFirst;
document.querySelector('.nameSecond').value = nameSecond;
document.querySelector('.checkedStatus').checked = checkedStatus;
return;
}
...
你可能会发现很容易破坏一个元素并用
替换它<input defaultValue={this.props.name}/>
像这样:
if(document.querySelector("#myParentElement")){
ReactDOM.unmountComponentAtNode(document.querySelector("#myParentElement"));
ReactDOM.render(
<MyComponent name={name} />,
document.querySelector("#myParentElement")
);
};
您也可以使用此版本的卸载方法:
ReactDOM.unmountComponentAtNode(ReactDOM.findDOMNode(this).parentNode);
答案 5 :(得分:0)
为参数“placeHolder”赋值。 例如: -
<input
type="text"
placeHolder="Search product name."
style={{border:'1px solid #c5c5c5', padding:font*0.005,cursor:'text'}}
value={this.state.productSearchText}
onChange={this.handleChangeProductSearchText}
/>
答案 6 :(得分:0)
相关问题
在控件上设置 defaulValue
不会更新 state
。
反向操作很完美:
state
设置为默认值,控件 UI 会正确更新,就像给出了 defaulValue
一样。代码:
let defaultRole = "Owner";
const [role, setRole] = useState(defaultRole);
useEffect(() => {
setMsg(role);
});
const handleChange = (event) => {
setRole(event.target.value );
};
// ----
<TextField
label="Enter Role"
onChange={handleChange}
autoFocus
value={role}
/>
答案 7 :(得分:0)
div
和 key
道具包围您的输入setDefaultValue
以重新渲染您的组件示例:
const [defaultValue, setDefaultValue] = useState(initialValue);
useEffect(() => {
setDefaultValue(initialValue);
}, false)
return (
<div key={defaultValue}>
<input defaultValue={defaultValue} />
</div>
)
答案 8 :(得分:0)
使用 value
而不是 defaultValue
并使用 onChange
方法更改输入的值。