React:无法访问传递的道具(但可以从路由器访问道具)
React: can't access passed props (but CAN access props from router)
名为 Edit 的子组件正在从路由 ('/:id/edit') 接收 props.match,但我无法访问从父组件 [=] 发送的 <Edit />
中的其他道具14=].
难道两种方式都不能发送道具吗?
我最初的问题是我想从 <Edit />
访问道具而不在 Chirp 页面上的编辑中呈现所有内容。所以我在编辑按钮点击时发送了道具。 <Edit />
正在渲染它的所有 html 否则很好。
console.log(this.props) 显示匹配项、位置和历史记录。我试过这个。props.match.params 和 this.props.user 等,但只得到 undefined.
Chirp.jsx(父组件 - 也是子组件)
import React, { Component, Fragment } from 'react';
import { BrowserRouter as Router, Link } from 'react-router-dom';
import 'isomorphic-fetch';
import Edit from './edit';
class Chirp extends Component {
constructor() {
super();
this.state = {
user: "",
text: ""
}
this.editClick = this.editClick.bind(this);
}
componentDidMount() {
fetch(`http://127.0.0.1:3000/api/chirps/${this.props.match.params.id}`)
.then(response => response.json())
.then(data => {
this.setState({
user: data.user,
text: data.text
})
})
.catch(err => console.log(err))
}
editClick() {
<Edit user={this.state.user} text={this.state.text} />
console.log("props passed")
}
render() {
return (
<div>
<Fragment>
<Link to="/" className="homelink" style={{ textDecoration: "none" }}>Home</Link>
</Fragment>
<div className="current">
<div className="flex-column">
<div className='chirps'>
<p>{this.state.user}: {this.state.text}</p>
<Fragment >
<Link to={`/${this.props.match.params.id}/edit`}><button onClick={this.editClick}>Edit</button></Link>
</Fragment>
<Fragment >
<Link to={`/${this.props.match.params.id}/delete`}><button className="delete">x</button></Link>
</Fragment>
</div>
</div>
</div>
</div>
)
}
}
export default Chirp;
edit.jsx(子组件)
import React, { Component, Fragment } from 'react';
import { BrowserRouter as Router, Link } from 'react-router-dom';
import 'isomorphic-fetch';
class Edit extends Component {
constructor() {
super();
this.state = {
newUser: "",
newText: ""
}
}
render() {
console.log(this.props)
return (
<div>
<Fragment>
<Link to="/" className="homelink" style={{ textDecoration: "none" }}>Home</Link>
</Fragment>
<h2>Edit Your Chirp</h2>
<div className="input">
<form action="">
<input
type="text"
placeholder={this.props.user}
size="10"
id="user"
name="user"
// onChange={this.inputHandler}
// defaultValue={this.props.user}
/>
<input
type="text"
placeholder={this.props.text}
size="60"
id="text"
name="text"
// onChange={this.inputHandler}
// defaultValue={this.state.text}
/>
<button
onClick={this.editChirps}
id="submit">
Submit
</button>
</form>
</div>
</div>
)
}
}
export default Edit;
app.jsx
import React, { Component, Fragment } from 'react';
import { BrowserRouter as Router, Route, Switch, Link } from 'react-router-dom';
import Home from './home'
import Chirp from './chirp'
import Edit from './edit'
import Delete from './delete'
class Navigation extends Component {
render() {
return (
<Router>
<Fragment>
<Switch>
<Route exact path="/" component={Home} />
<Route path="/:id/edit" component={Edit} />
<Route path="/:id/delete" component={Delete} />
<Route path="/:id" component={Chirp} />
</Switch>
</Fragment>
</Router>
)
}
}
export default Navigation;
你不能 render
这样的组件 onClick
。
另外,editClick
没有返回任何东西。
我的建议是将布尔值存储在 isEditMode
和 conditional render 组件的状态中:
editClick(){
this.setState(state => ({isEditMode: !state.isEditMode}));
}
并在渲染中:
{this.state.isEditMode && <Edit user={this.state.user} text={this.state.text} />}
这是一个小 运行 示例:
const Edit = ({ someProp }) => <input placeholder={someProp} />;
class App extends React.Component {
state = { isEditMode: false };
toggleEdit = () =>
this.setState(state => ({ isEditMode: !state.isEditMode }));
render() {
const { isEditMode } = this.state;
return (
<div>
<button onClick={this.toggleEdit}>Toggle Edit</button>
{isEditMode && <Edit someProp="Edit me" />}
</div>
);
}
}
const root = document.getElementById("root");
ReactDOM.render(<App />, root);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"/>
编辑
更新后,我现在看到您的问题是您为 <Edit />
呈现 Route
的方式。
您没有传递任何道具:
<Route path="/:id/edit" component={Edit} />
可以使用render prop。
这里的问题是该组件的数据不在根组件中,但这没关系,因为您可以在组件树下的任何级别呈现 <Route />
。
您可以在 this snippet
中查看 运行 示例
最初的问题是 props 没有传递到路由器 Link 中的 <Edit />
组件。最有效的解决方案来自这个 YouTube:Pass Props To React Router Link Component
只需使用以下语法将属性添加到 Link 中的 "to"。在 'state' 中传递道具。
<Link to={{
pathname: `/${this.props.match.params.id}/edit`,
state: {
user: this.state.user,
text: this.state.text
}
}}>
<button onClick={this.editClick}>Edit</button>
</Link>
然后在 Link(子)组件上,使用
访问道具
this.props.location.state.user
this.props.location.state.text
本页介绍的另一种解决方案也适用;不要在 app.jsx 中为这个 Link 定义路由,而是在父组件中定义它。这将需要更多的步骤:
导入路由、开关和编辑
重新排列渲染中的 Route 结构;即,将 return 包装在 <Router >
中,移回 Link,等等
将此内联函数添加到路由:render={route => <Edit match={route.match} user={this.state.user} text={this.state.text}
但此方法存在的一个问题是家 link 和 chirp 'user' 和 'text' 显示在编辑组件中。
子组件的问题是你已经在其中定义了构造函数方法,而没有将 props 传递给 super 和父组件的构造函数方法 component.This 这样你就永远不会在子组件中获得 props 。
有两种解法
1) 从子组件中移除构造方法
2) 如果出于某种原因不想删除构造函数,那么只需将 props 传递给其中的 super 和构造函数方法即可。
示例:
class Edit extends Component {
constructor(props) {
super(props);
this.state = {
newUser: "",
newText: ""
}
}
render() {
console.log(this.props)
}
}
希望这能解决您的问题
名为 Edit 的子组件正在从路由 ('/:id/edit') 接收 props.match,但我无法访问从父组件 [=] 发送的 <Edit />
中的其他道具14=].
难道两种方式都不能发送道具吗?
我最初的问题是我想从 <Edit />
访问道具而不在 Chirp 页面上的编辑中呈现所有内容。所以我在编辑按钮点击时发送了道具。 <Edit />
正在渲染它的所有 html 否则很好。
console.log(this.props) 显示匹配项、位置和历史记录。我试过这个。props.match.params 和 this.props.user 等,但只得到 undefined.
Chirp.jsx(父组件 - 也是子组件)
import React, { Component, Fragment } from 'react';
import { BrowserRouter as Router, Link } from 'react-router-dom';
import 'isomorphic-fetch';
import Edit from './edit';
class Chirp extends Component {
constructor() {
super();
this.state = {
user: "",
text: ""
}
this.editClick = this.editClick.bind(this);
}
componentDidMount() {
fetch(`http://127.0.0.1:3000/api/chirps/${this.props.match.params.id}`)
.then(response => response.json())
.then(data => {
this.setState({
user: data.user,
text: data.text
})
})
.catch(err => console.log(err))
}
editClick() {
<Edit user={this.state.user} text={this.state.text} />
console.log("props passed")
}
render() {
return (
<div>
<Fragment>
<Link to="/" className="homelink" style={{ textDecoration: "none" }}>Home</Link>
</Fragment>
<div className="current">
<div className="flex-column">
<div className='chirps'>
<p>{this.state.user}: {this.state.text}</p>
<Fragment >
<Link to={`/${this.props.match.params.id}/edit`}><button onClick={this.editClick}>Edit</button></Link>
</Fragment>
<Fragment >
<Link to={`/${this.props.match.params.id}/delete`}><button className="delete">x</button></Link>
</Fragment>
</div>
</div>
</div>
</div>
)
}
}
export default Chirp;
edit.jsx(子组件)
import React, { Component, Fragment } from 'react';
import { BrowserRouter as Router, Link } from 'react-router-dom';
import 'isomorphic-fetch';
class Edit extends Component {
constructor() {
super();
this.state = {
newUser: "",
newText: ""
}
}
render() {
console.log(this.props)
return (
<div>
<Fragment>
<Link to="/" className="homelink" style={{ textDecoration: "none" }}>Home</Link>
</Fragment>
<h2>Edit Your Chirp</h2>
<div className="input">
<form action="">
<input
type="text"
placeholder={this.props.user}
size="10"
id="user"
name="user"
// onChange={this.inputHandler}
// defaultValue={this.props.user}
/>
<input
type="text"
placeholder={this.props.text}
size="60"
id="text"
name="text"
// onChange={this.inputHandler}
// defaultValue={this.state.text}
/>
<button
onClick={this.editChirps}
id="submit">
Submit
</button>
</form>
</div>
</div>
)
}
}
export default Edit;
app.jsx
import React, { Component, Fragment } from 'react';
import { BrowserRouter as Router, Route, Switch, Link } from 'react-router-dom';
import Home from './home'
import Chirp from './chirp'
import Edit from './edit'
import Delete from './delete'
class Navigation extends Component {
render() {
return (
<Router>
<Fragment>
<Switch>
<Route exact path="/" component={Home} />
<Route path="/:id/edit" component={Edit} />
<Route path="/:id/delete" component={Delete} />
<Route path="/:id" component={Chirp} />
</Switch>
</Fragment>
</Router>
)
}
}
export default Navigation;
你不能 render
这样的组件 onClick
。
另外,editClick
没有返回任何东西。
我的建议是将布尔值存储在 isEditMode
和 conditional render 组件的状态中:
editClick(){
this.setState(state => ({isEditMode: !state.isEditMode}));
}
并在渲染中:
{this.state.isEditMode && <Edit user={this.state.user} text={this.state.text} />}
这是一个小 运行 示例:
const Edit = ({ someProp }) => <input placeholder={someProp} />;
class App extends React.Component {
state = { isEditMode: false };
toggleEdit = () =>
this.setState(state => ({ isEditMode: !state.isEditMode }));
render() {
const { isEditMode } = this.state;
return (
<div>
<button onClick={this.toggleEdit}>Toggle Edit</button>
{isEditMode && <Edit someProp="Edit me" />}
</div>
);
}
}
const root = document.getElementById("root");
ReactDOM.render(<App />, root);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"/>
编辑
更新后,我现在看到您的问题是您为 <Edit />
呈现 Route
的方式。
您没有传递任何道具:
<Route path="/:id/edit" component={Edit} />
可以使用render prop。
这里的问题是该组件的数据不在根组件中,但这没关系,因为您可以在组件树下的任何级别呈现 <Route />
。
您可以在 this snippet
中查看 运行 示例最初的问题是 props 没有传递到路由器 Link 中的 <Edit />
组件。最有效的解决方案来自这个 YouTube:Pass Props To React Router Link Component
只需使用以下语法将属性添加到 Link 中的 "to"。在 'state' 中传递道具。
<Link to={{
pathname: `/${this.props.match.params.id}/edit`,
state: {
user: this.state.user,
text: this.state.text
}
}}>
<button onClick={this.editClick}>Edit</button>
</Link>
然后在 Link(子)组件上,使用
访问道具this.props.location.state.user
this.props.location.state.text
本页介绍的另一种解决方案也适用;不要在 app.jsx 中为这个 Link 定义路由,而是在父组件中定义它。这将需要更多的步骤:
导入路由、开关和编辑
重新排列渲染中的 Route 结构;即,将 return 包装在 <Router >
中,移回 Link,等等
将此内联函数添加到路由:render={route => <Edit match={route.match} user={this.state.user} text={this.state.text}
但此方法存在的一个问题是家 link 和 chirp 'user' 和 'text' 显示在编辑组件中。
子组件的问题是你已经在其中定义了构造函数方法,而没有将 props 传递给 super 和父组件的构造函数方法 component.This 这样你就永远不会在子组件中获得 props 。
有两种解法
1) 从子组件中移除构造方法 2) 如果出于某种原因不想删除构造函数,那么只需将 props 传递给其中的 super 和构造函数方法即可。
示例:
class Edit extends Component {
constructor(props) {
super(props);
this.state = {
newUser: "",
newText: ""
}
}
render() {
console.log(this.props)
}
}
希望这能解决您的问题