【发布时间】:2019-03-25 00:17:54
【问题描述】:
我有一个从 React 构建的简单表单。提交后,如果错误再次出现,我希望渲染一个额外的 div 以在表单上显示错误。
现在我可以让它工作,但我不喜欢这个解决方案。我的解决方案基于这样的知识,即只有在渲染函数内部的状态发生变化时组件才会重新渲染(在本例中为 this.state.errorMessages)。所以我必须像这样明确地将 if 条件放在渲染函数中
renderError() {
var errArr = [];
for (var key in this.state.errorMessages) {
errArr = [...errArr, ...this.state.errorMessages[key]];
}
return (
<div className="alert alert-danger">
{errArr.map((err) => {
return <p>{err}</p>
})}
</div>
)
}
renderForm() {
return (
<form onSubmit={this.handleRegisterFormSubmit}>
<div className="form-group">
<label>First Name</label>
<input type="text" className="form-control" name="name" placeholder="Name" value={this.state.firstName} onChange={this.handleFirstNameChange} required/>
</div>
<div className="form-group">
<label>Last Name</label>
<input type="text" className="form-control" name="lastName" placeholder="Last Name" value={this.state.lastName} onChange={this.handleLastNameChange} required/>
</div>
<div className="form-group">
<label>Email address</label>
<input type="email" className="form-control" id="exampleInputEmail1" aria-describedby="emailHelp" placeholder="Enter email" value={this.state.email} onChange={this.handleEmailChange} />
<small id="emailHelp" className="form-text text-muted">We'll never share your email with anyone else.</small>
</div>
<div className="form-group">
<label>Password</label>
<input type="password" className="form-control" name="password" placeholder="Password" value={this.state.password} onChange={this.handlePasswordChange}/>
</div>
<div className="form-group">
<label>Password Confirmation</label>
<input type="password" className="form-control" name="password_confirmation" placeholder="Password Confirmation" value={this.state.passwordConfirmation} onChange={this.handlePasswordConfirmationChange}/>
</div>
<div>
<button type="submit" className="btn btn-primary">Submit</button>
<button type="button" className="btn btn-danger" onClick={this.handleCancelClick}>Cancel</button>
</div>
</form>
)
}
render () {
if (!this.state.errorMessages) {
return (
<div>
{this.renderForm()}
</div>
)
} else {
return (
<div>
{this.renderForm()}
{this.renderError()}
</div>
)
}
}
我不太喜欢这种方法,因为如果我有更多条件需要重新渲染,这可能会变得很糟糕。我希望有一个解决方案,即在实际渲染函数中没有太多逻辑并将其提取出来。比如……
renderError() {
if (!this.state.errorMessages) {
return;
}
var errArr = [];
for (var key in this.state.errorMessages) {
errArr = [...errArr, ...this.state.errorMessages[key]];
}
return (
<div className="alert alert-danger">
{errArr.map((err) => {
return <p>{err}</p>
})}
</div>
)
}
render () {
<form onSubmit={this.handleRegisterFormSubmit}>
<div className="form-group">
<label>First Name</label>
<input type="text" className="form-control" name="name" placeholder="Name" value={this.state.firstName} onChange={this.handleFirstNameChange} required/>
</div>
<div className="form-group">
<label>Last Name</label>
<input type="text" className="form-control" name="lastName" placeholder="Last Name" value={this.state.lastName} onChange={this.handleLastNameChange} required/>
</div>
<div className="form-group">
<label>Email address</label>
<input type="email" className="form-control" id="exampleInputEmail1" aria-describedby="emailHelp" placeholder="Enter email" value={this.state.email} onChange={this.handleEmailChange} />
<small id="emailHelp" className="form-text text-muted">We'll never share your email with anyone else.</small>
</div>
<div className="form-group">
<label>Password</label>
<input type="password" className="form-control" name="password" placeholder="Password" value={this.state.password} onChange={this.handlePasswordChange}/>
</div>
<div className="form-group">
<label>Password Confirmation</label>
<input type="password" className="form-control" name="password_confirmation" placeholder="Password Confirmation" value={this.state.passwordConfirmation} onChange={this.handlePasswordConfirmationChange}/>
</div>
<div>
<button type="submit" className="btn btn-primary">Submit</button>
<button type="button" className="btn btn-danger" onClick={this.handleCancelClick}>Cancel</button>
</div>
{this.renderError}
</form>
}
这会引发错误,因为它抱怨 this.renderError 应该作为函数调用。但是当我把它作为 this.renderError() 错误将永远不会呈现,因为它不会在错误再次出现时自动调用。
-----------更新----------
另外,为什么我不能执行以下操作
render () {
<div>
<form onSubmit={this.handleRegisterFormSubmit}>
...
</form>
{if (this.state.errorMessages) {this.renderError()}}
</div>
}
这会引发控制台错误
未捕获的错误:模块构建失败:SyntaxError: Unexpected token (117:13)
---------更新2------------
本质上,我正在寻找一种解决方案,在渲染函数内部,当状态发生变化时,我可以轻松地显示整个代码块。在 Vue 中,我可以做类似的事情
<form>
<input type="text">
</form>
<div v-if="hasError">
<div class="alert alert-danger">{{something}}</div>
</div>
Can I do something as easy as this in React?
【问题讨论】:
-
把它当作 this.renderError() 是正确的。现在您需要了解为什么它不重新渲染。可能是因为您没有使用 setState 函数来更新状态。也许您可以分享您如何设置错误消息?
-
将逻辑放入渲染中是不好的做法。如果语句在您的 dom 中不起作用。此外,触发 this.renderError() 在这里没有多大意义,因为您只需要迭代您的错误。请在下面查看我的答案。
-
你可以做的是三元条件。但是如果 if(this.state.errorMessages) 是一个空对象,它可能总是为真。相反,请使用
{Object.keys(this.state.errorMessages).length ? this.renderError() : null}或{Object.keys(this.state.errorMessages).length && this.renderError()} -
在上面的那种情况下,这并不是关于我应该使用 if 还是三元条件,看起来 react 不喜欢在 render 的 {} 中使用这种 if 语句。 Iv 在下面的答案中添加了评论。感谢您的帮助
标签: javascript reactjs