user6517903
user6517903

Reputation:

Callback function from parent to child in React

I have a parent App and a child component Login. In the Login component, the user can login properly, and I can store the user details in setState. But I want to pass this state to the parent App through a callback function from the parent through the function named userState.

Here is the parent App:

const { BrowserRouter, Link, Switch, Route, browserHistory } = ReactRouterDOM;

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      currentUser: ""
    }
  }
  userState = (user) => {
    this.setState = {
      currentUser: user
    }
  }
  render() {
    return (
      <BrowserRouter>
        <div>
          <Nav />
          <Switch>
            <Route exact path="/someroute1">
              <Someroute1 />
            </Route>
            <Route path="/login">
              <Login userState={this.userState} currentUser={this.state.currentUser} />
            </Route>
            <Route path="/route2">
              <Someroute2 />
            </Route>
          </Switch>
          <Footer />
        </div>
      </BrowserRouter>
    );
  }
}

ReactDOM.render(<App />, document.querySelector(".container"));

Here is the child Login:

class Login extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            username: "",
            password: "",
            currentUser: this.props.currentUser
        }
    }
    handleChange = event => {
        this.setState({ [event.target.id]: event.target.value })
    }
    handleSubmit = event => {
        event.preventDefault();
        fetch("/sessions", {
            body: JSON.stringify(this.state),
            method: "POST",
            headers: {
                Accept: "application/json, text/plain, */*",
                "Content-Type": "application/json"
            }
        })
            .then(loggedInUser => {
                return loggedInUser.json();
            }).then(jsonedUser => {
                this.props.userState(jsonedUser); // <- this doesn't seem to work
                console.log('Current User is:', this.state.currentUser) // <- this.state.currentUser is blank
            })
            .catch(error => console.log(error));
    };

    render() {
        return (
            <React.Fragment>
                <h1>Login</h1>
                <form onSubmit={this.handleSubmit}>
                    <label htmlFor="username">Username</label>
                    <input type="text" id="username" name="username" value={this.state.username} onChange={this.handleChange} />
                    <label htmlFor="password">Password</label>
                    <input type="password" id="password" name="password" value={this.state.password} onChange={this.handleChange} />
                    <input type="submit" value="Submit" />
                </form>
            </React.Fragment>
        );
    }
}

I have checked out this tutorial https://medium.com/@ruthmpardee/passing-data-between-react-components-103ad82ebd17 and checked out a lot of answers from stackoverflow, but somehow my callback function doesn't do anything.

Any help is appreciated!

Upvotes: 0

Views: 5102

Answers (2)

Shreyas D
Shreyas D

Reputation: 69

This might help you

Parent

import Child from '../child.js';

class Parent extends Component {

 getValue = (data) =>{
  //Login data
  console.log(data);
 }

 render(){
  return(
   <div>
    <Child getValue={this.getValue} />
   </div>
  )
 }
}

Child

 class Child extends Component {

 onLogin = () =>{
  this.props.getValue('any data to parent here');
 }

 render(){
  return(
   <div>
    <button onClick={()=>this.onLogin}>Login</button>
   </div>
  )
 }
}

Upvotes: 1

Oliver
Oliver

Reputation: 237

this is the error you are receiving.

First off, Parent JS looks great!

in childJS there are some issues, they begin right here:

    this.state = {
    ...  
    currentUser: this.props.currentUser
}

and presumably they follow down into the rest of the component (i.e where you are displaying what the user sees).

What you need to do is keep the data flow consistent. ChildJS does not need state, it just needs to show the parent state (which is passed down by props).

ParentJS (state: user, setState) =>

Child JS will then be: render() { return ( {currentUser} )} with say

Upvotes: 0

Related Questions