javascript - How can I simply pass data from a component one page to a component on another page in React/Next.js? - TagMerge
4How can I simply pass data from a component one page to a component on another page in React/Next.js?How can I simply pass data from a component one page to a component on another page in React/Next.js?

How can I simply pass data from a component one page to a component on another page in React/Next.js?

Asked 1 years ago
1
4 answers

I think there are two questions here:

  1. How do I pass data between two NextJS pages?
  2. Why isn't my link updating when the suggest values are updated?

There are a few different ways you can pass data between pages, but the querystring params is probably the method I would use. Although I would not use the description in the querystring if possible. You can do this by using the NextJS <Link /> component

However, it appears you have tried something like this and the link is not updating. The reason for this is how the markers data is set. You have set this as a const in the component, which tells React not to monitor changes to this object. When onFromSuggestSelect fires, it updates the object properties and then... nothing. React thinks that there can't be any changes to the <Link /> as nothing has changed in the Parent.

This is why we have React State. If you change your markers const to instead use the useState hook, you should find that the implemented <link /> will update when the value is changed.

A word of warning; read the docs thoroughly if you have not used the useState hook before so that you understand how to implement this correctly.

I hope this solves your problem.

Source: link

1

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

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

Source: link

1

index.js (simplified)
{/* Import used next and style objects */ }
import Head from 'next/head'
import styles from '../styles/Home.module.css'

{/* Import react-bootstrap */ }
import { Container, Row, Col } from 'react-bootstrap'

{/* Import geosuggest */ }
import Geosuggest from 'react-geosuggest'

{/* Import used components */ }
import NavigationBar from '../components/NavigationBar'
import Footer from '../components/Footer'

{/* Import and use runtime vars for Google API */ }
import getConfig from "next/config"
const { publicRuntimeConfig } = getConfig()
const GoogleApiUrl = `https://maps.googleapis.com/maps/api/js?key=${publicRuntimeConfig.MAPS_JAVASCRIPT_API_KEY}&libraries=places`

export default function Home() {

  const markers = {
    from: {description: "", lat: 0, lng: 0},
    to: {description: "", lat: 0, lng: 0}
  }

  const onFromSuggestSelect = (suggest) => {
    console.log("New FROM location selected: \"" + suggest.description + "\"");
    markers.from.description = suggest.description
    markers.from.lat = suggest.location.lat
    markers.from.lng = suggest.location.lng
  }

  const onToSuggestSelect = (suggest) => {
    console.log("New TO location selected: \"" + suggest.description + "\"");
    markers.to.description = suggest.description
    markers.to.lat = suggest.location.lat
    markers.to.lng = suggest.location.lng
  }

  return (
    <div>
      <Head>
        <title>MyApp</title>
        <meta name="description" content="MyApp" />
        <link rel="icon" href="/favicon.ico" />
        <script src={GoogleApiUrl}></script>
      </Head>

      <NavigationBar/>

      <div className={styles.container}>
        <main>
          <Container>
            <Row className="text-center">
              <Col md={1}></Col>
              <Col md={5}><Geosuggest data-test-id="autocomplete-start-test" placeholder="From..." onSuggestSelect={onFromSuggestSelect} country="gb"  minLength="3" /></Col>
              <Col md={5}><Geosuggest data-test-id="autocomplete-end-test" placeholder="To..." onSuggestSelect={onToSuggestSelect} country="gb"  minLength="3" /></Col>
              <Col md={1}></Col>
            </Row>
          </Container>
        </main>

        <Footer/>

      </div>
    </div>
  )
}
results.js (simplified)
{/* Import used next and style objects */ }
import Head from 'next/head'
import styles from '../styles/Home.module.css'

{/* Import used react-bootstrap objects */ }
import { Container } from 'react-bootstrap'

{/* Import used components */ }
import NavigationBar from '../components/NavigationBar'
import Footer from '../components/Footer'
import Map from '../components/Map'

{/* Import and use runtime vars for Google API */ }
import getConfig from "next/config"
const { publicRuntimeConfig } = getConfig()
const GoogleApiUrl = `https://maps.googleapis.com/maps/api/js?key=${publicRuntimeConfig.MAPS_JAVASCRIPT_API_KEY}&libraries=places`

export default function Home() {

    const markers = {
        from: {description: "", lat: 0, lng: 0},
        to: {description: "", lat: 0, lng: 0}
      }

  return (
    <div>
      <Head>
        <title>MyApp</title>
        <meta name="description" content="MyApp" />
        <link rel="icon" href="/favicon.ico" />
        <script src={GoogleApiUrl}></script>
      </Head>

      <NavigationBar/>

      <div className={styles.container}>
        <main>
            <Container>
                {/* MARKERS NEEDS TO BE PASSED IN ON THE LINE BELOW */}
                <Map markers={markers}/> 
            </Container>
        </main>
      </div>
      
      <Footer/>

    </div>
  )
}
Map.js (component)
import React from "react"
import { GoogleMap, Marker } from "@react-google-maps/api"

export default class Map extends React.Component {
    render() {
        // Set the map to fill its container
        const containerStyle = { width: '500px', height: '500px' }
          
        // Set the map to show the entire UK on initial load
        const center = { lat: 54.476422, lng: -3.397340 }
        const zoom = 6

        // Return the map with the above defaults
        return(
            <GoogleMap mapContainerStyle={containerStyle} center={center} zoom={zoom}>
                <Marker position={{ lat: this.props.markers.from.lat, lng: this.props.markers.from.lng }} />
                <Marker position={{ lat: this.props.markers.to.lat, lng: this.props.markers.to.lng }} />
            </GoogleMap>
        )
    }
}

Source: link

1

First, you'll need to create two components, one parent and one child.
import React from 'react'

export default function Parent() {
  return (
    <div>
      
    </div>
  )
}
import React from 'react' export default function Parent() { return ( <div> </div> ) } Parent.js
import React from 'react'

export default function Child() {
    return (
        <div>
            
        </div>
    )
}
Next, you'll import the child component in the parent component and return it.
import React from 'react'
import Child from './Child';

export default function Parent() {
  return (
    <div>
      <Child/>
    </div>
  )
}
Then you'll create a function and a button to trigger that function. Also, you'll create a state using the useState Hook to manage the data.
import React from 'react'
import Child from './Child';
import { Button } from 'semantic-ui-react';
import { useState } from 'react';
import './App.css';

export default function Parent() {
  const [data, setData] = useState('');
  
  const parentToChild = () => {
    setData("This is data from Parent Component to the Child Component.");
  }
  return (
    <div className="App">
      <Child/>
      
      <div>
        <Button primary onClick={() => parentToChild()}>Click Parent</Button>
      </div>
    </div>
  )
}
Pass the data as props when you are calling the child component like this:
<Child parentToChild={data}/>
Case 1: If you are using a functional component, simply catch the parentToChild in the parameters.
import React from 'react'

export default function Child({parentToChild}) {
    return (
        <div>
            {parentToChild}
        </div>
    )
}
Case 2: If you have a class component, then just use this.props.parentToChild.
import React, { Component } from 'react'

export default class Child extends Component {
    render() {
        return (
            <div>
                {this.props.parentToChild}
            </div>
        )
    }
}
When we click the Click Parent button, we will see the data as output on the screen.
import React from 'react'
import Child from './Child';
import { Button } from 'semantic-ui-react';
import { useState } from 'react';
import './App.css';

export default function Parent() {
  const [data, setData] = useState('');
  
  const parentToChild = () => {
    setData("This is data from Parent Component to the Child Component.");
  }
  return (
    <div className="App">
      <Child parentToChild={data}/>
      
      <div className="child">
        <Button primary onClick={() => parentToChild()}>Click Parent</Button>
      </div>
    </div>
  )
}
First, you need to create a function in the parent component called  childToParent and an empty state named data.
const [data, setData] = useState('');

const childToParent = () => {
   
}
Then, pass the childToParent function as a prop to the child component.
<Child childToParent={childToParent}/>
Pass the data into the the parentToChild function as parameters.
import React from 'react'
import { Button } from 'semantic-ui-react';

export default function Child({childToParent}) {
    const data = "This is data from Child Component to the Parent Component."
    return (
        <div>
            <Button primary onClick={() => childToParent(data)}>Click Child</Button>
        </div>
    )
}
Next, in the parent component, accept this data in the childToParent function as a parameter. Then set the data using the useState hook.
import './App.css';
import { useState } from 'react';
import Child from './Child';

function Parent() {
  const [data, setData] = useState('');
  
  const childToParent = (childdata) => {
    setData(childdata);
  }

  return (
    <div className="App">
      <div>
        <Child/>
      </div>
    </div>
  );
}

export default Parent;
Next, show that data variable in the return function.
import './App.css';
import { useState } from 'react';
import Child from './Child';

function Parent() {
  const [data, setData] = useState('');
  
  const childToParent = (childdata) => {
    setData(childdata);
  }

  return (
    <div className="App">
     {data}
      <div>
        <Child childToParent={childToParent}/>
      </div>
    </div>
  );
}

export default Parent;
Just call an alert method in the childToParent function and pass that function as a prop to the child component.
import './App.css';
import Child from './Child';

function Parent() {
  const childToParent = () => {
    alert("This is an alert from the Child Component")
  }

  return (
    <div className="App">
      <div className="child">
        <Child childToParent={childToParent}/>
      </div>
    </div>
  );
}

export default Parent;
And in the child component, accept the childToParent function as a prop. Then assign it to an onClick event on a button.
import React from 'react'
import { Button } from 'semantic-ui-react';

export default function Child({childToParent}) {
    return (
        <div>
            <Button primary onClick={() => childToParent()}>Click Child</Button>
        </div>
    )
}

Source: link

Recent Questions on javascript

    Programming Languages