反应:无法访问传递的道具(但可以从路由器访问道具)

时间:2018-09-25 20:27:01

标签: javascript reactjs react-router react-props react-component

一个名为Edit的子组件正在从路由('/:id / edit')接收props.match,但我无法访问由父组件<Edit />发送的<Chirp />中的其他props。

两种方法都无法发送道具吗?

最初的问题是我想从<Edit />访问道具,而无需在“调频”页面的“编辑”中渲染所有内容。因此,我在“编辑”的按钮点击上发送了道具。 <Edit />会使其所有html正常显示。

console.log(this.props)显示匹配,位置和历史记录。我已经尝试过this.props.match.params和this.props.user等,但只能得到未定义。

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;

3 个答案:

答案 0 :(得分:3)

您不能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"/>

修改
更新之后,我现在看到的问题是您为Route渲染<Edit />的方式。

您没有传递任何道具:

 <Route path="/:id/edit" component={Edit} />

您可以使用render prop

这里的问题是该组件的数据不在根组件上,但是可以在组件树下的任何级别渲染<Route />

您可以在this snippet

中看到正在运行的示例

答案 1 :(得分:0)

最初的问题是道具没有传递到路由器Link中的<Edit />组件。最有效的解决方案来自以下YouTube:Pass Props To React Router Link Component

使用以下语法在“链接”中简单地添加属性。以“状态”传递道具。

<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>

然后在“链接(子)”组件上,使用来访问道具

this.props.location.state.user
this.props.location.state.text

此页面上提供的另一种解决方案也可以使用;无需在app.jsx中定义此Link的路由,而是在父组件中定义它。这将需要更多步骤:

导入路线,切换和编辑 在渲染中重新排列Route结构;即在<Router >中将return换行,将主链接移回原位,等等 将此内联函数添加到路由:render={route => <Edit match={route.match} user={this.state.user} text={this.state.text}

但是此方法带来的一个问题是主页链接以及线性调频调“用户”和“文本”显示在“编辑”组件中。

答案 2 :(得分:0)

子组件的问题是您在其中定义了构造方法,而没有将道具传递给父组件的super和构造方法。这样您将永远不会在子组件内部获得道具。

有两种解决方法。

1)从子组件中删除构造函数方法 2)如果由于某种原因不想删除构造函数,则只需将props传递给其中的super和constructor方法。

示例:

class Edit extends Component {
    constructor(props) {
    super(props);
    this.state = {
        newUser: "",
        newText: ""
    }
 }

 render() {
    console.log(this.props)
 }
}

希望这可以解决您的问题