Home > database >  How to pass input value from one component to the other component( where api & data display code are
How to pass input value from one component to the other component( where api & data display code are

Time:10-31

I have two components where one comp provides a search input field where the user will enter data(e.g; city name) and another comp provides the main weather data( based on the user search input from comp 1) like temp, wind, etc.. how should I pass the user input to the API so it will render the data of that city. I have been stuck on this issue for the last 3 days. any solution?

Comp1 (search comp)

import React, { useState } from "react";
import "../Componentstyle/search.css";
export default function Search() {
  const [location, setLocation] = useState();
  
const handlesubmit = (event)=>{
  event.preventDefault();
  setLocation(event.target.value)
}
  return (
    <>
    <div className="main">
      <nav className="istclass">
        <form className="form">
          <div className="search">
            <input
              value={location}
              placeholder="search city"
              className="searchbox"
              onChange={(e) => setLocation(e.target.value)}
            />

            <button className="nd" type="button" onClick={handlesubmit}>
              Submit
            </button>
          </div>
        </form>
      </nav>
    </div>
    </>
  );
}

Comp2 (maindata comp)

import React, { useState, useEffect } from "react";
import "../Componentstyle/Main.css";
export default function Maindata() {
  const [data, setData] = useState();


  let city = "mansehra";

  let weather = async () => {
    // if(!city)return;
    const key = "XYZ";
    await fetch(
      `https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${key}&units=metric&formatted=0`
    )
      .then((response) => response.json())
      .then((actualData) => setData(actualData));
  };
  useEffect(() => {
    weather();
  }, []);

  if (!data) {
    return <div>Loading...</div>;
  }

  const link = `http://openweathermap.org/img/w/${data.weather[0].icon}.png`;

  return (
    <>
    <div className="maindata">
      <div className="city">{data.name}</div>
      <div className="temp">{data.main.temp} C</div>
      <div className="icon">
        <img src={link} alt="not found" />{" "}
      </div>
      <div className="feel">feels Like {data.main.feels_like} C</div>
      <div className="wind">Wind {data.wind.speed} Km/hr</div>
      <div className="cloudy">{data.weather[0].main}</div>
      <div className="humidity">humidity {data.main.humidity}%</div>
      <div className="sunrise">
        sunrise :- {new Date(data.sys.sunrise * 1000).toUTCString()}{" "}
      </div>
      <div className="sunset">
        sunset :- {new Date(data.sys.sunset * 1000).toUTCString()}
      </div>
    </div>
    </>
  );
}

App.js Comp

import "./App.css";
import Maindata from "./Components/Maindata";
import Search from "./Components/Search";



function App() {
  
  return (
    <div className="mainpage">
      <div className="searchComp">
        <Search />
      </div>
      <div className="details">
        <Maindata />

  );
}

export default App;

CodePudding user response:

You can use the context API. You would create a context for location. The context's provider would wrap both the search component as well as the component that performs the API call (MainData?) You would set the context value in the search component and get the context value in the MainData component.

The LocationProvider could look like this:

import React, { createContext, useState } from 'react'

export const LocationContext = createContext(null)

const LocationProvider = ({ children }) => {
  const [ location, setLocation ] = useState('')
  return (
    <LocationContext.Provider value={{location, setLocation}}>
      {children}
    </LocationContext.Provider>
  )
}

export default LocationProvider

If both components are wrapped in this provider, you can access setLocation() in the SearchComponent by importing LocationContext and then doing this:

const { setLocation } = useContext(LocationContext)

and in the other component you can access the location in a similar manner:

const { location } = useContext(LocationContext)

CodePudding user response:

You can simply Lift State Up. Move the Search component's state up to a common ancestor component and pass the state and state updater callback function down as props to the components needing them.

Example:

App

function App() {
  const [location, setLocation] = useState();

  return (
    <div className="mainpage">
      <div className="searchComp">
        <Search {...{ location, setLocation }} />
      </div>
      <div className="details">
        <Maindata city={location} />
      </div>
    </div>
  );
}

Search

export default function Search({ location, setLocation }) {
  const handlesubmit = (event) => {
    event.preventDefault();
    setLocation(event.target.value);
  };

  return (
    <div className="main">
      <nav className="istclass">
        <form className="form">
          <div className="search">
            <input
              value={location}
              placeholder="search city"
              className="searchbox"
              onChange={(e) => setLocation(e.target.value)}
            />

            <button className="nd" type="button" onClick={handlesubmit}>
              Submit
            </button>
          </div>
        </form>
      </nav>
    </div>
  );
}

Maindata

export default function Maindata({ city = "mansehra" }) {
  const [data, setData] = useState();

  const weather = async (city) => {
    const key = "XYZ";
    await fetch(
      `https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${key}&units=metric&formatted=0`
    )
      .then((response) => response.json())
      .then((actualData) => setData(actualData));
  };

  useEffect(() => {
    if (city) {
      weather();
    }
  }, [city]);

  if (!data) {
    return <div>Loading...</div>;
  }

  const link = `http://openweathermap.org/img/w/${data.weather[0].icon}.png`;

  return (
    <>
    <div className="maindata">
      <div className="city">{data.name}</div>
      <div className="temp">{data.main.temp} C</div>
      <div className="icon">
        <img src={link} alt="not found" />{" "}
      </div>
      <div className="feel">feels Like {data.main.feels_like} C</div>
      <div className="wind">Wind {data.wind.speed} Km/hr</div>
      <div className="cloudy">{data.weather[0].main}</div>
      <div className="humidity">humidity {data.main.humidity}%</div>
      <div className="sunrise">
        sunrise :- {new Date(data.sys.sunrise * 1000).toUTCString()}{" "}
      </div>
      <div className="sunset">
        sunset :- {new Date(data.sys.sunset * 1000).toUTCString()}
      </div>
    </div>
    </>
  );
}
  • Related