Leon Bogod
Leon Bogod

Reputation: 428

how to pass state in react router to components

im trying to make a seperate page / component for searching and am wondering how i would pass the state to a different component ? i want to copy and paste everything in the render/return part into a different component and then access that page using react router, how would I do that? any help is greatly appreciated!

    import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import Weather from "./Weather.js";
import Skycons from "react-skycons"
import { geticon } from "./geticon.js"

import ToggleDisplay from 'react-toggle-display';
import Form   from "./Form.js";
import Layout from "./layout.js";
import Hike  from "./Hike.js";
import 'bootstrap/dist/css/bootstrap.min.css';

import {FormControl, FormGroup, ControlLabel, HelpBlock, Checkbox, Radio, Button} from 'react-bootstrap';
import { BrowserRouter as Router, Route, Link } from "react-router-dom";



const API_KEY = "2a41aeea56aabfb9ff1218730fc32426";

 class App extends React.Component {

  state = {
    temperature: "",
    city: "",
    city2:"",
    country: "",
    msg: "",
    pressure: "",
    humidity: "",
    description: "",
    rain:"",
    main:"Drizzle",
    icon: "09d",
    error: "",
    date: "",
    month:"",
    lat:"",
    show: false,
    lng:"",
    year:"",
    clouds:""

  }

  handlenum1Change (evt) {



let temp = (evt.target.value);




}

  getDate() {
   var date = new Date().getDate();
      var month = new Date().getMonth() + 1;
      var year = new Date().getFullYear();

   this.setState({ date,year,month});

}

 componentDidMount() {
    this.getDate();
  }


  getWeather = async (e) => {
    e.preventDefault();

      this.setState({ showResults: true });
    const city = e.target.city.value;

    const api_call = await fetch(`https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${API_KEY}&units=metric`);
    https://www.hikingproject.com/data/get-trails-by-id?ids=7000108,7002175,7005207,7001726,7005428&key=YOU
    const data = await api_call.json();

    if (city) {
      this.setState({
        temperature: data.main.temp,
        city: data.name,
        clouds:data.clouds.all,
        main: data.weather[0].main,
        icon: data.weather[0].icon,
        rain: data.rain,
        pressure: data.main.pressure,
        humidity: data.main.humidity,
        description: data.weather[0].description,
        error: ""
      });

    } else {
      this.setState({
        temperature: undefined,
        city: undefined,
        country: undefined,
        humidity: undefined,
        description: undefined,
        pressure:undefined,
        rain : undefined,
        error: "Please enter the values."
      });
    }

var clouds= data.clouds.all;

if (clouds>30){
this.setState({
  msg:" Poor  conditions for stargazing!! "
})
}
  else{

   this.setState({
  msg: " Good conditions for stargazing! no rain in forecast! "
})
  }

}




  getTrail = async (e) => {
    e.preventDefault();


    const city = e.target.city2.value;
  this.setState({
      show: !this.state.show
    });

    const country = e.target.country.value;


    const api_call = await fetch(`https://api.wunderground.com/api/b1049a092a7f69ea/astronomy/q/${country}/${city}.json`);

    const data = await api_call.json();

   if (city) {
      this.setState({
        moon_phase: data.moon_phase.ageOfMoon,
        moon_hour: data.moon_phase.hemisphere,
          moon_rise: data.moon_phase.moonrise.hour,
           moon_rises: data.moon_phase.moonrise.minute,
        moon_state: data.moon_phase.phaseofMoon,
        moon_set: data.moon_phase.moonset.hour,
       moon_sets: data.moon_phase.moonset.minute,
        sunset: data.sun_phase.sunset.hour,
         sunsets: data.sun_phase.sunset.minute,
         sunrise:data.sun_phase.sunrise.hour,
         sunrises:data.sun_phase.sunrise.minute


      });
    } else {
      this.setState({
         moon_phase: undefined,
        sunset: undefined
      });
    }
  }




//   const BasicExample = () => (
//   <Router>
//     <div>
//       <ul className="navbar-nav ml-auto">

//         <li className="nav-item">
//           <Link to="/about">About</Link>
//         </li>
//         <li className="nav-item">
//           <Link to="/topics">Topics</Link>
//         </li>
//       </ul>

//       <hr />

//       <Route path="/about" component={About} />
//       <Route path="/topics" component={Topics} />
//     </div>
//   </Router>
// );


  render() {
    return (
      <div>


      <div>
        <br></br><br></br><br></br><br></br><br></br><br></br> 
      <div className="container">

    <div className="row">

      <div id="city">

              <div className="form-group mb-2">

                <div className="form-group mx-sm-3 mb-2">


                  <form className="form-inline" onSubmit={this.getWeather} >

                  <input type="text" name="city"  className="form-control" onChange={this.handlenum1Change} placeholder="Input City..."/>


    <button className="btn btn-primary">Get Weather</button>


    </form> 


                  <Weather className="fish"
                    city={this.state.city}
                    temperature={this.state.temperature}
                    humidity={this.state.humidity}
                 clouds={this.state.clouds}
                       pressure={this.state.pressure}
                    description={this.state.description}
                    rain={this.state.rain}
                    icon={this.state.icon}
                    error={this.state.error}
                  />

 <h3> {this.state.msg} </h3>

          <div className="clearfix"> 

      <div className="date"><p id="d"> {this.state.date}/{this.state.month}/{this.state.year}</p> 


<div>
    <Form getTrail={this.getTrail} />





              {this.state.moon_phase &&   <div> moon_phase: {this.state.moon_phase}</div>  }
               {this.state.sunset && this.state.sunsets && <div className="row"> <p> sunset Time: {this.state.sunset} </p> : <p> {this.state.sunsets} </p> </div> }

               {this.state.sunrise && this.state.sunrises &&  <div className="row"> <p> sunrise  Time: {this.state.sunrise} </p> : <p> {this.state.sunrises} </p></div> }

                   {this.state.moon_set && this.state.moon_sets && <div className="row"> <p> moonset:  {this.state.moon_set} </p> : <p> {this.state.moon_sets} AM</p> </div> }

                <div class="w-100"> </div>
                  {this.state.moon_rise && this.state.moon_rises &&    <div className="row">     <p>moonrise - {this.state.moon_rise} </p> : <p> {this.state.moon_rises} PM</p> </div> }



               {this.state.moon_state &&   <p> {this.state.moon_state} moon  </p> }
               {this.state.moon_hour && <p> hemisphere: {this.state.moon_hour} </p>  }
 </div>
 </div>
 </div>

</div>
</div>
 </div>

 </div>
 </div>
 </div>

 </div>


     );
  }
};

export default App;

Upvotes: 2

Views: 9004

Answers (5)

Ali Asgari
Ali Asgari

Reputation: 1

Imagine that:

We have PageFour as a component and We have 'name' as a 'prop' in this component.

We need to pass a 'name' from a parent to 'PageFour' component.

First of all, we need a constructor and super in the parent:

constructor(props) {
 super(props);
     this.state = {

         name:"anyname"

     }

}

then in parent:

render() {
    return (
        <Router>
        <div className="container">


        <Route path="/user" component={() => (
            <PageFour  name={this.state.name}/> )}/>

        </div>
    </Router>
    );
}

Upvotes: 0

noxasaxon
noxasaxon

Reputation: 2423

First in your index.js file you want to wrap <App> with a Router

    ReactDOM.render(
        <Router>
            <App />
        </Router>
      document.getElementById('root')
    );

Second step: in app.js in the render() you can wrap everything in a <Switch>. Inside the switch you make your routes with each one having whatever component(s) you want to display.

    render(){
        return(
            <div>
              <Switch>
                <Route exact path="/"> {/* needs to say "exact" for routes that 
                                         will be duplicated like "/" which is in 
                                         every route */}
                  <div>
                    <Weather/>
                    <Form/>
                  </div>
                </Route>

                <Route to="/">
                    <SearchComponent>
                </Route>
              </Switch>
            </div>
    )}

So thats how router works. For your other question, there a couple tricks ill give you because im not sure what you need:

You can pass the whole state simply by sending it as a prop to a component:

`<Weather state={this.state}/>`

I doubt this is best practices but its good to know how react works. If you wanted to change the state from the child component Weather you would have to pass it a function as well that handles changes with something similar to this:

    changeState = (newState) => {
        this.setState(newState);
    }
    <Weather state={this.state} changeParentState={this.changeState}/>
    enter code here

Inside Weather:

    componentDidMount() {
        this.setState({parentState: this.props.state)}
    }

And when you need to update the parent state : 

    this.props.changeParentState(newState);

Another React tip is if you want to have a component inside another component you can do this:

<App>
 <ChildComponent/>
</App>

and by putting this.props.children into the Render statement it will display that component!

(inside App)

    render() {
       return(
               <div>
                 anything you want to add
                 {this.props.children}
                 </div>
             )
    }

Upvotes: 0

waz
waz

Reputation: 1253

Firstly. Passing the state around:

The way you pass state to a different component is using react-redux

You set up a global state, then access it through connect

import { connect } from 'react-redux';

https://redux.js.org/basics/usage-with-react

--

Secondly. If you want to use a component in another component, you just call that component and pass through the props.

Super Basic Example.

import Products from '../../components/Products';
import ContentRow from '../../components/contentRow';

export default class Shop extends React.PureComponent {
  render() {

    return (

      <div>
        <ContentRow
         imageURL="https://placeimg.com/400/400/nature"
         shortText="This is the short text that will display"
        />
        <Products></Products>
      </div>
    );
  }
}

Where the <contentRow shortText="..."> is a props that you are passing through to the component that renders.

Hope this helps.

Upvotes: 1

Dkouk
Dkouk

Reputation: 339

you need to send that state as props to component you want using render at Route, like that: <Route path='/component' render={(props) => <MyComponent {...props} state={this.state} />} />

Upvotes: 0

Liam
Liam

Reputation: 6743

If I understood you correctly, so you need to use render instead of component in react-router

  <Route path="/about" render={()=> <About parentState={this.state} />} />

And you can access them in About component like

this.props.parentState.main // should render "Drizzle"

Upvotes: 3

Related Questions