[javascript] React 입력 defaultValue가 상태로 업데이트되지 않습니다.
반응으로 간단한 양식을 만들려고하는데 데이터가 양식의 defaultValue에 제대로 바인딩되는 데 어려움이 있습니다.
내가 찾고있는 동작은 다음과 같습니다.
- 내 페이지를 열 때 텍스트 입력 필드가 데이터베이스의 AwayMessage 텍스트로 채워 져야합니다. 이것이 “샘플 텍스트”입니다.
- 데이터베이스의 AwayMessage에 텍스트가없는 경우 이상적으로는 텍스트 입력 필드에 자리 표시자를 갖고 싶습니다.
그러나 지금은 페이지를 새로 고칠 때마다 텍스트 입력 필드가 비어 있습니다. (입력에 입력 한 내용이 제대로 저장되고 지속되지만) AwayMessage가 빈 개체 일 때 입력 텍스트 필드의 html이로드되지만 awayMessage가로드 될 때 새로 고쳐지지 않기 때문이라고 생각합니다. 또한 필드의 기본값을 지정할 수 없습니다.
명확성을 위해 일부 코드를 제거했습니다 (예 : 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}
답변
defaultValue는 초기로드에만 해당됩니다.
입력을 초기화하려면 defaultValue를 사용해야하지만 상태를 사용하여 값을 변경하려면 값을 사용해야합니다. 개인적으로 나는 초기화하는 경우 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 호출을 할 수 없습니다.
getInitialState가 실행 된 후 api 호출을해야합니다. 귀하의 경우에는 componentDidMount에서 할 것입니다. https://facebook.github.io/react/tips/initial-ajax.html 예제를 따르십시오. .
또한 반응으로 구성 요소 수명주기를 읽는 것이 좋습니다. https://facebook.github.io/react/docs/component-specs.html .
수정 및로드 상태로 다시 작성
개인적으로 나는 렌더링에서 로직을 사용하고 내 상태에서 ‘로드’를 사용하고 양식이로드되기 전에 글꼴 멋진 스피너를 렌더링하는 것을 선호하는 경우 전체를 수행하고 싶지 않습니다. 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>
그것은 그것을 덮을 것입니다. 이제 그것은 상태와 가치를 사용하는 형태에 대한 한 가지 방법입니다. value 대신 defaultValue를 사용한 다음 제출할 때 refs를 사용하여 값을 가져올 수도 있습니다. 그 경로로 가면 데이터를 가져 와서 양식에 소품으로 전달할 외부 쉘 구성 요소 (일반적으로 고차 구성 요소라고 함)를 사용하는 것이 좋습니다.
전반적으로 반응 문서를 끝까지 읽고 몇 가지 자습서를 수행하는 것이 좋습니다. 거기에는 많은 블로그가 있으며 http://www.egghead.io 에는 좋은 자습서가 있습니다. 내 사이트 http://www.openmindedinnovations.com 에도 몇 가지 항목이 있습니다 .
답변
이를 수정하는 또 다른 방법은 key
입력 을 변경하는 것 입니다.
<input ref="text" key={this.state.awayMessage ? 'notLoadedYet' : 'loaded'} onChange={this.onTextChange} defaultValue={awayMessageText} />
업데이트 : 이것은 upvotes를 얻으므로 콘텐츠가로드되는 동안 disabled
또는 readonly
prop을 올바르게 가져야한다고 말해야 하므로 ux 경험을 감소시키지 않습니다.
그리고 네, 그것은 해킹 일 가능성이 가장 높지만 작업을 완료합니다 .. 😉
답변
최선의 해결책은 아닐 수도 있지만, 코드의 모든 곳에서 재사용 할 수 있도록 아래와 같은 구성 요소를 만들 것입니다. 기본적으로 이미 반응했으면 좋겠습니다.
<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
답변
초기 값을 설정하는 가장 안정적인 방법은 render () {} 외에도 componentDidMount () {}를 사용하는 것입니다.
...
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);
답변
매개 변수 “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}
/>