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 没有返回任何东西。

我的建议是将布尔值存储在 isEditModeconditional 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)
 }
}

希望这能解决您的问题