0

I have one component in which I have one button and I am calling one node js service on that. I am getting a response back from that service and I want to pass that response on next component to display a data there. Below is my component which is doing a node js call.

import { FormGroup } from "react-bootstrap";
import "bootstrap/dist/css/bootstrap.css";
import axios from "axios";


export default class Abc extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            data: {}
        }
        this.handleClick = this.handleClick.bind(this);
    }

    handleClick = (e) => {
        e.preventDefault();
        axios.get(url)
            .then(res => {
                this.setState({
                    data: res.data// I need this variable to pass to next component Pqr where I can use it for display purpose.
                })
                this.props.history.push("/Pqr",{ response:res.data});
            })
    };

    render() {

        return (
            <form >
                <button className="btn btn-info btn-sm" onClick={this.handleClick} style={{ whitespace: 'nowrap' }} >
                    Launch
                    </button>
            </form>
        )

    }
}


My Pqr component code is as below.

import React from "react";

export default class ModelLaunch extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
        }
    }
    render() {
        const state = this.props.location.state
        return (
        <h1>This page will display model Inputs : {state} </h1>
        )
    }
}
Nilesh
  • 518
  • 1
  • 9
  • 26
  • This might help you https://stackoverflow.com/questions/44121069/how-to-pass-params-with-history-push-link-redirect-in-react-router-v4 – Shilpa Mar 31 '20 at 08:59
  • there is only one component here. you need a child component to pass this data to if you're just using state declared in a component. – Joe Lloyd Mar 31 '20 at 08:59
  • @JoeLloyd I have added my Pqr component code as well. I am still not able to access the data. – Nilesh Mar 31 '20 at 09:37
  • But they have no relationship. you cant send data that you declare in a component if the receiver is not a child. If you need to do this you should implement the contextHook or better still Redux – Joe Lloyd Mar 31 '20 at 09:41
  • @JoeLloyd how to use hooks, I am new in react and working on one poc, So not aware all the things in react. Could you please help. – Nilesh Mar 31 '20 at 09:43
  • 1
    its too big to go into in a comment. go read the hooks docs and read about react state management. You need to understand these 2 fundamentals, there is no easy fix for this issue outside of proper state management. – Joe Lloyd Mar 31 '20 at 09:51

2 Answers2

0

I have solved above problem with other way. Instead of calling a node js service on Abc component I am just redirecting it to new coponent and in new component's componentDidMount() method I am calling a node js service and storind a data in props. In this way I have my data on new copmonent. Below is my updated code in Abc component now.

import { FormGroup } from "react-bootstrap";
import "bootstrap/dist/css/bootstrap.css";
import axios from "axios";


export default class Abc extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            data: {}
        }
        this.handleClick = this.handleClick.bind(this);
    }

    handleClick = (e) => {
        e.preventDefault();
                this.props.history.push("/Pqr");
            })
    };

    render() {

        return (
            <form >
                <button className="btn btn-info btn-sm" onClick={this.handleClick} style={{ whitespace: 'nowrap' }} >
                    Launch
                    </button>
            </form>
        )

    }

And in pqr coponent's code as below

import React from "react";
import axios from "axios";

export default class Pqr extends React.Component{
 constructor(props)
 {
  super(props);
  this.state = { 
   data :[]
  }
 }

 componentDidMount(){

        axios.get(url).then((res) => {
            console.log("res****",res.data)
            this.setState({
                data:res.data
            })
        }).catch((err) =>{
            console.log("err", err)
        })
    }
 render()
 {
  return(
  <h1>This page will display data</h1>
  )
 }
}
Nilesh
  • 518
  • 1
  • 9
  • 26
-1

I see you're changing a route (using react-router?).

Remember that this.setState is async and specific for your component, when you call this.props.history.push('/Pqr'), maybe the this.state.data is not updated yet.

To share this data through different routes in the same react project, I actually know that you can:

If its not the case, and you just want to pass the property down or above the hierarchy tree, in addition to the comments above, maybe it can help:

As you probably know, react projects are composed of components that are put all together to work in a specific way. In the example below, there are two components (father and child)

import React from 'react';

// We can say that this component is "below" Father
function Child(props) {
  return (
    <button>
      Hey, I'm a button!
    </button>
  );
}

// We can say that this component is "above" Child
function Father(props) {
  return (
    <div>
      <Child />
    </div>
  );
}

I couldn't find in the provided code/question, one child component, maybe you forgot to write it?

If the response is "yes", I'll create a fictional component called... FictionalComponent (I'm a Genius!), and pass the data on state as a property named... data.

In order to pass this property, if its the case, you just need to update your render method to look like this:

  render() {
    return (
      <form >
        <button 
          className="btn btn-info btn-sm" 
          onClick={this.handleClick} 
          style={{ whitespace: 'nowrap' }} 
        >
          Launch
          <FictionalComponent data={this.state.data} />
        </button>
      </form>
    )
  }

This way, when this.state.data changes, the FictionalComponent will be re-rendered with the new data value.

But, maybe you want the reverse operation and you need to pass the this.state.data to the component above your Abc, listed there when the button is pressed.

To achieve it you need to have a "Father" component to your Abc, the "Father" component must provide an onDataChanged callback in order to capture the event. This callback will receive the data and handle it.

In this case, I'll create another component to be the component above your Abc. I'll name it... AboveAbcComponent, perfect!

...

class AboveAbcComponent extends React.Component {
  constructor(props) {
    this.state = {
      dataFromChild: null
    };

    this.onDataChanged = this.onDataChanged.bind(this);
  }

  onDataChanged(dataReceived) {
    console.log("Yey! It works!");
    this.setState({ dataFromChild: dataReceived });
  }

  render() {// Just the passed props changes here
    ...
      <Abc 
        onDataChanged={this.onDataChanged}
      />
    ...
  }
}

export default class Abc extends React.Component {
  constructor(props) { ... } // No changes here

  handleClick = (e) => {
    e.preventDefault();
    axios.get(url)
      .then(res => {
        this.setState({
          data: res.data
        });

        this.props.onDataChanged(res.data);

        this.props.history.push("/Pqr"); // I really didn't understand Why this push is here... but ok
      })
  };

  render() { ... } // No changes here
}

Hope it helps, have fun!