javascript - 反应状态:未捕获的类型错误:无法读取未定义的属性“值”
问题描述
我正在关注 Wes Bos 的React for Beginners课程,在 State 视频中,他编写了以下代码:
import React, { Component } from 'react';
class AddFishForm extends Component {
nameRef = React.createRef();
priceRef = React.createRef();
statusRef = React.createRef();
descRef = React.createRef();
imageRef = React.createRef();
createFish = event => {
event.preventDefault();
const fish = {
nameRef: this.nameRef.value.value,
priceRef: parseFloat(this.priceRef.value.value),
statusRef: this.statusRef.value.value,
descRef: this.descRef.value.value,
imageRef: this.imageRef.value.value,
}
console.log(this); //or console.log(fish)
}
render() {
return (
<form className="fish-edit" onSubmit={this.createFish}>
<input name="name" ref={this.nameRef} type="text" placeholder="Name"/>
<input name="price" ref={this.priceRef} placeholder="Price"/>
<select name="status" ref={this.statusRef}>
<option value="available">Fresh!</option>
<option value="unavailable">Sold Out!</option>
</select>
<textarea name="desc" ref={this.descRef} placeholder="Desc"/>
<input name="image" ref={this.imageRef} type="text" placeholder="Image"/>
<button type="submit">+ Add Fish</button>
</form>
)
}
}
export default AddFishForm;
每当我尝试单击“添加鱼”按钮时,都会出现错误:
AddFishForm.js:14 Uncaught TypeError: Cannot read property 'value' of undefined
at AddFishForm._this.createFish (AddFishForm.js:14)
at HTMLUnknownElement.callCallback (react-dom.development.js:149)
at Object.invokeGuardedCallbackDev (react-dom.development.js:199)
at invokeGuardedCallback (react-dom.development.js:256)
at invokeGuardedCallbackAndCatchFirstError (react-dom.development.js:270)
at executeDispatch (react-dom.development.js:561)
at executeDispatchesInOrder (react-dom.development.js:583)
at executeDispatchesAndRelease (react-dom.development.js:680)
at executeDispatchesAndReleaseTopLevel (react-dom.development.js:688)
at forEachAccumulated (react-dom.development.js:662)
at runEventsInBatch (react-dom.development.js:816)
at runExtractedEventsInBatch (react-dom.development.js:824)
at handleTopLevel (react-dom.development.js:4820)
at batchedUpdates$1 (react-dom.development.js:18932)
at batchedUpdates (react-dom.development.js:2150)
at dispatchEvent (react-dom.development.js:4899)
at interactiveUpdates$1 (react-dom.development.js:18987)
at interactiveUpdates (react-dom.development.js:2169)
at dispatchInteractiveEvent (react-dom.development.js:4876)
我想在他的代码中指出某些事情。他不使用带有关联绑定语句的构造函数(props)函数,而是选择将 createFish 转换为箭头函数。我看到的几乎所有其他关于 State 的问题都使用构造函数。我应该效仿,还是可以使用箭头符号(尽管它还不是标准)?
此外,在相关StorePicker.js
文件中,他编写了以下代码,旨在通过路由将您从 StorePicker 页面带到 App 页面。然而,当我在我的应用程序中单击“转到商店”按钮时,该应用程序只会重新加载而不会继续。我应该做些什么不同的事情?
代码StorePicker.js
:
import React, { Fragment } from 'react';
import { getFunName } from '../helpers';
class StorePicker extends React.Component { //OR: ...extends Component (if you import { Component }).
constructor () {
super();
console.log('Create a component!')
this.goToStore = this.goToStore.bind(this);
}
myInput = React.createRef();
goToStore(event) {
//1. Stop the form from submitting.
event.preventDefault();
//2. Get the text from that input. Not going to select using document.querySelector or jQuery here.
/*IMPORTANT!
We need to bind ‘this’ to the StorePicker component so that it remains accessible from a member function.
Either declare a constructor, as shown at the top, or turn goToStore into a function w/ arrow notation.
goToStore = (event) => {}
*/
const storeName = this.myInput.value.value;
//3. Change the page to /store/whatever-they-entered. This uses push state instead of actually moving to a new page.
this.props.history.push(`/store/${storeName}`);
}
render() {
return (
<Fragment>
<h1>StorePicker</h1>
<form className="store-selector">
<h2>Please enter a store.</h2>
<input type="text"
ref={this.myInput}
required placeholder="Store name"
defaultValue={getFunName()}>
</input>
<button type="submit">Visit Store »
</button>
</form>
</Fragment>
)
}
}
export default StorePicker;
对于Router.js
:
import React from 'react';
import { BrowserRouter, Route, Switch } from 'react-router-dom';
import StorePicker from './StorePicker';
import App from './App';
import NotFound from './NotFound';
const Router = () => (
<BrowserRouter>
<Switch>
<Route exact path="/" component={StorePicker} />
<Route path="/store/:storeId" component={App} />
<Route component={NotFound} /> {/*Default catch-all. */}
</Switch>
</BrowserRouter>
);
export default Router;
解决方案
问题参考
访问 refs 时,需要访问current
属性。
当 ref 被传递给 in 中的元素时
render
,对节点的引用可以在current
ref 的属性中访问。
ref.current.<property>
代码
const fish = {
nameRef: this.nameRef.current.value,
priceRef: parseFloat(this.priceRef.current.value),
statusRef: this.statusRef.current.value,
descRef: this.descRef.current.value,
imageRef: this.imageRef.current.value,
}
问题 1
他不使用带有关联绑定语句的构造函数(props)函数,而是选择将 createFish 转换为箭头函数。我看到的几乎所有其他关于 State 的问题都使用构造函数。我应该效仿,还是可以使用箭头符号(尽管它还不是标准)?
AddFishForm
没有状态,并且所有作为函数的类属性都是箭头函数,因此它们不需要this
在构造函数中显式绑定到它们。此外,您也可以在没有构造函数的情况下声明状态类属性。
class Foo extends Component {
state = {...}
...
问题2
...应该通过路由将您从 StorePicker 页面带到 App 页面的代码。然而,当我在我的应用程序中单击“转到商店”按钮时,该应用程序只会重新加载而不会继续。我应该做些什么不同的事情?
这里的问题是按钮有type="submit"
并且在一个表单中,当点击它会使表单采取默认操作,即尝试提交表单并重新加载页面。this.goToStore
也似乎根本没有使用。
<form className="store-selector">
<h2>Please enter a store.</h2>
<input type="text"
ref={this.myInput}
required
placeholder="Store name"
defaultValue={getFunName()}
/>
<button type="submit"> // <-- causes form to submit and take default actions
Visit Store »
</button>
</form>
解决方案
- 将按钮类型更改为
type="button"
并添加一个onClick
处理程序,onClick={this.goToStore}
- 附加
this.goToStore
到表单的onSubmit
处理程序<form onSubmit={this.goToStore}>
我猜goToStore
是为了被表格使用。
<form
className="store-selector"
onSubmit={this.goToStore}
>
<h2>Please enter a store.</h2>
<input type="text"
ref={this.myInput}
required
placeholder="Store name"
defaultValue={getFunName()}
/>
<button type="submit">
Visit Store »
</button>
</form>
推荐阅读
- laravel-5.7 - SQLSTATE[HY000] [2002] laravel 中的连接被拒绝
- node.js - 如何安装 node-sqlite3,但跳过构建步骤并提供我自己的 sqlite3 构建?
- sql-server - 将表添加到新 EF 模型时,商店提供者的数据读取器出现错误消息
- bash - 语法错误不确定它在说什么或如何修复它
- amazon-athena - 如何从直方图中选择与最大值对应的键?
- java - Spring Security Acl 对象
- c# - 尝试捕获不显示 formatException 的错误消息
- spring - Spring Security手动身份验证不起作用
- ms-access - 如何按周计算一年信息
- javascript - Webpack 加载资源失败。捆绑.js 404