admin管理员组

文章数量:1404603

A child ponent called Edit is receiving props.match from the route ('/:id/edit') but I cannot access other props in <Edit /> sent from the parent ponent <Chirp />.

Is it not possible to send props with both methods?

My initial problem was that I wanted to access props from <Edit /> without rendering everything in Edit on the Chirp page. So I sent the props on Edit's button click. <Edit /> is rendering all its html fine otherwise.

console.log(this.props) shows Match, Location, and History. I've tried this.props.match.params and this.props.user, etc. but only get undefined.

Chirp.jsx (parent - also a child ponent)

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);
    }

    ponentDidMount() {
        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 (child ponent)

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="/" ponent={Home} />
                        <Route path="/:id/edit" ponent={Edit} />
                        <Route path="/:id/delete" ponent={Delete} />
                        <Route path="/:id" ponent={Chirp} />
                    </Switch>
                </Fragment>
            </Router>
        )
    }
}

export default Navigation;

A child ponent called Edit is receiving props.match from the route ('/:id/edit') but I cannot access other props in <Edit /> sent from the parent ponent <Chirp />.

Is it not possible to send props with both methods?

My initial problem was that I wanted to access props from <Edit /> without rendering everything in Edit on the Chirp page. So I sent the props on Edit's button click. <Edit /> is rendering all its html fine otherwise.

console.log(this.props) shows Match, Location, and History. I've tried this.props.match.params and this.props.user, etc. but only get undefined.

Chirp.jsx (parent - also a child ponent)

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);
    }

    ponentDidMount() {
        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 (child ponent)

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="/" ponent={Home} />
                        <Route path="/:id/edit" ponent={Edit} />
                        <Route path="/:id/delete" ponent={Delete} />
                        <Route path="/:id" ponent={Chirp} />
                    </Switch>
                </Fragment>
            </Router>
        )
    }
}

export default Navigation;
Share Improve this question edited Sep 25, 2018 at 21:31 cDub asked Sep 25, 2018 at 20:27 cDubcDub 5181 gold badge6 silver badges21 bronze badges 1
  • editClick is a no-op here; you create and discard a ponent and return undefined. I think what you meant to do is set a flag saying you're editing, and check that flag to decide whether or not you should render the edit ponent. – Dave Newton Commented Sep 25, 2018 at 20:35
Add a ment  | 

3 Answers 3

Reset to default 3

You cannot render a ponent onClick like that.
Plus, editClick is not returning anything.

My suggestion is to store a Boolean in state like isEditMode and conditional render the ponent:

editClick(){
  this.setState(state => ({isEditMode: !state.isEditMode}));
}

and in render:

{this.state.isEditMode && <Edit user={this.state.user} text={this.state.text} />}

Here is a small running example:

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./ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"/>

Edit
After you update, i now see that your problem is the way you render the Route for <Edit />.

You are not passing any props:

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

You can use the render prop.

The issue here is that your data for this ponent is not at the root ponent, but that's ok as you can render a <Route /> at any level down the ponent tree.

You can see a running example in this snippet

The original problem is that props were not getting passed to the <Edit /> ponent in the router Link. The most efficient solution es from this YouTube: Pass Props To React Router Link Component

Simply add properties to "to" in the Link with the syntax below. Pass props in '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>

Then on the Link (child) ponent, access the props with

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

Another solution presented on this page will also work; Instead of defining the route for this Link in app.jsx, define it in the parent ponent. This would require a few more steps:

import Route, Switch, & Edit rearrange the Route structure in render; i.e. wrap return in <Router >, move home Link, etc add this inline function to the route: render={route => <Edit match={route.match} user={this.state.user} text={this.state.text}

But an issue this method presents is that the home link and chirp 'user' and 'text' show in the Edit ponent.

The problem with the child ponent is that you have defined the constructor method inside it without passing props to the super and constructor method for parent ponent.This way you will never get the props inside child ponent .

There are two solution of it.

1) Remove constructor method from the child ponent 2) If you don't want to remove the constructor for some reason then simply pass props to the super and constructor method in it .

Example :

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

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

Hope this will solve your problem

本文标签: javascriptReact can39t access passed props (but CAN access props from router)Stack Overflow