我在Reaction中编写了一个函数,该函数通过呈现的提交表单接受用户的输入,使用它来查询API并更新表单中的p标记内容。这是以下代码:
var textfield = ""
function Form (){
const [ name, getNFT ] = useState("")
let postName = (e) =>{
let output
async function getInfo(e) {
e.preventDefault()
try {
const resp = await axios.post("/hey_honey", {
name
})
console.log(resp.data)
output = resp.data
return output
} catch (error) {
console.error(error)
}
}
getInfo(e).then(output =>{console.log("output is outside of function scope", output)
})
textfield = output
return textfield
}
return (
<div className="App">
<form onSubmit={postName}>
<input type="text" value={name} onChange={(e) => getNFT(e.target.value)}/>
<button type="submit" >Get Collection's Gallery</button>
<p>{textfield}</p>
</form>
</div>
)
}
我已经成功地获得了我想要的JSON字符串。问题是,我似乎无法更新呈现的表单,因为它不在postName的函数作用域之外,或者由postName修改的任何内容,即使在表单之外示例化,实际上也无法更改状态。
我一度认为这很可能是因为这是使用类的一个更合适的示例,但是我不能使用useState,因此无法存储在提交表单中写出的内容。(**编辑:**经过一些研究后,我可以使用类来完成这项工作。从技术上讲,我不需要将useState用于表单,而是可以使用setState并简单地将setState示例化为空字符串。它看起来如下所示,为了方便起见,我们只有一个函数,它只返回输入,而不是异步函数:
class NameForm extends React.Component {
constructor(props) {
super(props);
this.state = {value: '', textfield: ''};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
this.setState({value: event.target.value});
}
handleSubmit(event) {
this.setState({textfield: event.target.value})
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Name
<input type="text" value={this.state.value} onChange={this.handleChange} />
</label>
<input type="submit" value="Submit" />
<p>{this.state.textfield}</p>
</form>
);
}
}
然而,我们仍然遇到更新表单本身的问题。)
编辑这是表单元素的特定问题吗?当有人在博客上发表评论时,有没有我应该使用的完全不同的组件?我之所以被表单所吸引,是因为它们接受用户输入,然后给您提供一些您可以操作的东西,但一旦您设置它们,它们是否就是不可变的?
在撰写本文时,我开始考虑现在应该导出一个存储值,在我的例子中是Textfield,然后将其传递到一个全新的组件中。将会更新。
1条答案
按热度按时间eqqqjvef1#
问题是,我似乎无法更新呈现的表单,因为它不在postName的函数作用域之外,或者由postName修改的任何内容,即使在表单之外示例化,实际上也无法更改状态。
说到React,在一天结束的时候,如果你想让它重新呈现,你需要更新React状态。您在这里使用
textfield
所做的是更新一个JS变量,但Reaction无法知道该变量是否不同,因此它不知道要重新呈现。注意你在用你的
input
做什么。因为您已经设置了value
,所以它是一个“受控输入”,因此您可以看到您输入的文本的唯一原因是因为您正在更新React状态,并在每次按键时触发重新呈现。您可以对网络请求的结果执行相同的操作。一旦请求完成,您可以更新一段状态,这将触发重新呈现。请注意,如果您不使用该状态(例如,通过呈现其中的一部分),您将无法仅通过浏览器查看它来判断Reaction已经重新呈现。
下面是一个稍有不同的示例,它根据表单输入发出网络请求并呈现结果。(对于这个API来说,变量名没有多大意义,只是想保持较小的差异)。
这里有一个版本,它做了同样的事情,但稍微清理了一下,只是为了进行比较:
(Sandbox)。需要说明的是,以上几点绝对不是完美的!
撇开REACT不谈,要记住的一件事是,
then
内的函数内的代码将在getInfo(e)
完成从Internet获取其信息时运行,但之后的行立即运行而不等待,因为getInfo
调用返回Promise
。在JS中,这样的异步逻辑是非阻塞的!您可以在上面看到如何使用await
来避免需要then
和嵌套。(但是,值得记住的是,async/await
只是承诺和.then
的花哨语法,所以可以用其中一个做的任何事情都可以用另一个做。)此外,由于函数作用域的限制,您将无法在
then
函数之外访问output
。您必须在该函数内部进行变量赋值,或者使用Async AWait将事情变得稍微平坦一些。我一度认为这很可能是因为这是使用类的一个更合适的示例,但是我不能使用useState,因此无法存储在提交表单中写出的内容。我错过了什么吗?
在Reaction中,过去需要为更复杂的组件(如具有状态的组件)使用类,并且只能使用表示组件的函数。但是自从它们引入钩子以来,类组件和功能组件可以以不同的方式做相同的事情,所以您在这里所做的一切都很好!我会坚持使用功能组件,就像你在学习的时候所拥有的那样。
在React之外,在处理状态时,类是一个很好的选择(尽管您也可以用嵌套函数做相同的事情)。但是您仍然需要一些方法来将对您的普通JS类状态的更新Map到React状态。首先,我主要关注在Reaction中存储状态,当您构建更大的应用程序时,您可以花一些时间学习如何将它们绑定到您自己的定制类中,或者引入一个状态管理库(Redux可能是最著名的)来为您处理这一问题。