rahul Dev
rahul Dev

Reputation: 25

How to fetch the input value of a form in another component with React Hooks

I have used Axios with Reach Hooks. Is there any way to fetch the updated input value from form.js file so that I can use it to update the axios.get link in ApiData.js file? When the user types a value, I want to fetch that value and use in the ApiData.js file so that the value can be updated in axios.get. I have tried a lot of ways to do that by passing the updatedInputVal in the form.js file to a function and then trying to access it in the ApiData.js file. Nothing worked. I'm a beginner. So please let me know if you are unclear about the issue. Thanks in advance

This is the form.js file

import React, {useState} from 'react';

function UseForm(){
    const[inputValue, setInputValue] = useState({
        search: "",
        contactName:"",
        contact:""
    })

    function handleChange(e){
        const {name, value} = e.target;
        setInputValue(previousValue=>{
            if(name === "search"){
                return{
                    search: value,
                    contactName:previousValue.contactName,
                    contact:previousValue.contact   
                }
            }
        })
    }

    function onFormSubmit(event){
        let updatedInputVal = setInputValue(inputValue.search)
        event.preventDefault();
        return updatedInputVal;//Want to fetch this value and use it in the ApiData.js component
    }



    return ( 
        <div className="form-container">
            <div className="input-div">
                <form onSubmit={onFormSubmit}>
                    <input className="form-input" onChange={handleChange} type="text" name="search" value={inputValue.search} placeholder="Search TV Shows"/>
                </form>
            </div>
            <div className="btn-div">
                <button type="submit" className="btn">Submit</button>    
            </div>
        </div>)
}



export default UseForm;

This is the ApiData.js file

import React, {useState, useEffect} from 'react';
import axios from 'axios';
    

const FetchApiData = () =>{
    const [data, setData] = useState([])
    useEffect(()=>{
        async function fetchData(){
        const resquest =  await axios.get(`http://api.tvmaze.com/search/shows?q=${//want to insert here the updated input value the user types}`)
        const appData =  resquest.data[0].show.image.medium;
        setData(appData)
        return appData
    }  fetchData()
    }, [])
    
    return (
            <div className="section-image">
                <img src={data} alt=""/>
            </div>
            ) 
}

export default FetchApiData

App.js file

import React from 'react';
import Nav from "./Nav";
import UseForm from "./Form"
import FetchApiData from './ApiData'


function App(){
    return (
    <div>
        <Nav 
        src={`${process.env.PUBLIC_URL}/images/logo.png`}
        title = "CONTACT US"
        />
        <UseForm/>
        <FetchApiData/>
    </div>)
}

export default App

Upvotes: 2

Views: 1720

Answers (2)

Aakash
Aakash

Reputation: 23727

You need to lift the inputValue state to App component and pass it via props:

function App(){
    const [inputValue, setInputValue] = useState({
        search: "",
        contactName:"",
        contact:""
    })
    return (
    <div>
        <Nav 
        src={`${process.env.PUBLIC_URL}/images/logo.png`}
        title = "CONTACT US"
        />
        <UseForm inputValue={inputValue} setInputValue={setInputValue}/>
        <FetchApiData inputValue={inputValue}/>
    </div>)
}

function UseForm({inputValue, setInputValue}){
 // ...
}

Also, a state-management solution like Redux can also help in managing state separately from component so that you don't need to pass state via props like shown above.

Upvotes: 1

Daniel Oram
Daniel Oram

Reputation: 8411

Because the App component is the parent of both FetchApiData and UseForm you can simply just handle the state of this value using the App component and pass this property to both children.

App component:

function App(){

    // declare state object here
    const [inputValue, setInputValue] = useState({
        search: "",
        contactName:"",
        contact:""
    });

    return (
    <div>
        <Nav 
        src={`${process.env.PUBLIC_URL}/images/logo.png`}
        title = "CONTACT US"
        />
        {/* Pass props to each component */}
        <UseForm inputValue={inputValue} setInputValue={setInputValue}/>
        <FetchApiData inputValue={inputValue}/>
    </div>)
}

UseForm component:

function UseForm({inputValue, setInputValue}){
    // Remove this
    // const[inputValue, setInputValue] = useState({
    //     search: "",
    //     contactName:"",
    //     contact:""
    // })

    // keep everything else the same
}

FetchApiData component:

const FetchApiData = ({inputValue}) =>{
    const [data, setData] = useState([])
    useEffect(()=>{
        async function fetchData(){
        const resquest =  await axios.get(`http://api.tvmaze.com/search/shows?q=${inputValue}`)
        const appData =  resquest.data[0].show.image.medium;
        setData(appData)
        return appData
    }  fetchData()
    }, [inputValue])
    
    return (
            <div className="section-image">
                <img src={data} alt=""/>
            </div>
            ) 
}

FetchApiData will re-render every time inputValue changes. Just take note of that unless it is the intended behaviour.

Upvotes: 3

Related Questions