Reputation: 428
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
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
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
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
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
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