简体   繁体   中英

React - calling the same function from separate onSubmit and onClick events

I am having an issue with calling an async function in React to an outside API where I'm looking to call the function from two separate events, an onSubmit of a form, and an onClick from the results of a separate search.

I have the following React components:

App.js:

import React, { useState, useEffect } from 'react'
import './App.css';
import Ticker from './compoments/Ticker'
import SearchTicker from './compoments/SearchTicker'
import TickerResults from './compoments/TickerResults'
import SearchCompanyProfile from './compoments/SearchCompanyProfile';

function App() {
  const [company, setCompany] = useState([])
  const [price, setPrice] = useState([])
  const [symbol, setSymbol] = useState([])

     async function fetchCompanyProfile(e) {
      let company = '';
      if(e.target.target.ticker.value){
        company = e.target.ticker.value
        } else {
        company = e.target.innerHTML;
        } 
      console.log(company)
      e.preventDefault() 
      e.target.reset()
        const companyData = await fetch(https://someapicompany.com/profile/${company}?apikey=xyz)
          .then(res => res.json())
          .then(data => data)
            setCompany({data: companyData})
    }

    console.log(company.data)
 
  return (
    <div className="App">
        <SearchTicker getTicker={fetchTicker}/>
        <SearchCompanyProfile getCompanyProfile={fetchCompanyProfile}/>
        <TickerResults ticker={symbol} getTicker={fetchCompanyProfile}/>
        <CompanyProfile company={company}/>
    </div>
  );
}

export default App;

SearchCompanyProfile.js

import React from 'react'

const SearchCompanyProfile = (props) => {

    return (
        <div>
             <form onSubmit={props.getCompanyProfile} >
                <input type="text" name="ticker" placeholder="Enter Ticker..."/>
                <button value="Search" type="submit">
                Search
                </button>
            </form>
        </div>
    )
}

export default SearchCompanyProfile;

SearchTicker.js

import React from 'react'

const SearchTicker = (props) => {


    return (
        <div>
            <form onSubmit={props.getTicker}>
                <input type="text" name="symbol" placeholder="Enter Compamy Name..."/>
                <button value="Search" type="submit">
                Search
                </button>

            </form>
        </div>
    )
}

export default SearchTicker;

TickerResults.js

import React from 'react'

const TickerResults = (props) => {
    console.log(props)
    return (
        <div>
            {props.ticker.data && props.ticker.data.map(x => <p name="ticker" value={x.symbol} onClick={props.getTicker}>{x.symbol}</p>)}
        </div>
    )
}

export default TickerResults;

My goal is to call the async function fetchCompanyProfile from both submitting the SearchCompanyProfile form and clicking on the ticker from the tickerResults component.

I have tried both:

async function fetchCompanyProfile(e) {
      let company = '';
      if(e.target.ticker.value){
        company = e.target.ticker.value;
        } else {
        company = e.target.innerHTML;
        } 
      console.log(company)
      e.preventDefault() 
      e.target.reset()
        const companyData = await fetch(https://someapicompany.com/profile/${company}?apikey=xyz)
          .then(res => res.json())
          .then(data => data)
            setCompany({data: companyData})
    }

    console.log(company.data)

-and-

async function fetchCompanyProfile(e) {
      let company = '';
      if(e.target.innerHTML){
        company = e.target.innerHTML;
        } else {
        company = e.target.ticker.value;
        } 
      console.log(company)
      e.preventDefault() 
      e.target.reset()
        const companyData = await fetch(https://someapicompany.com/profile/${company}?apikey=xyz)
          .then(res => res.json())
          .then(data => data)
            setCompany({data: companyData})
    }

    console.log(company.data)

Under both instances it works if the correct event happens in the right order but in the first case, I run into "value cannot be run on undefined" if I use the onClick event through tickerResults component, and in the second case, the innerHTML is just the form inputs from the the searchCompanyProfile form so the fetch is not called with the correct value.

I realize this is a long winded question but any suggestions would be appreciated.

Thy this, you need to call setCompany({ data }) inside of then because it's promise

 function App() { const [company, setCompany] = useState([]); const [price, setPrice] = useState([]); const [symbol, setSymbol] = useState([]); function fetchCompanyProfile(e) { let company = ''; if(e.target.target.ticker.value){ company = e.target.ticker.value } else { company = e.target.innerHTML; } console.log(company); e.preventDefault(); e.target.reset(); fetch('https://someapicompany.com/profile/${company}?apikey=xyz').then(res => res.json()).then(data => { setCompany({ data }) }); } console.log(company.data) return ( <div className="App"> <SearchTicker/> <SearchCompanyProfile getCompanyProfile={fetchCompanyProfile}/> <TickerResults ticker={symbol} getTicker={fetchCompanyProfile}/> <CompanyProfile company={company}/> </div> ); }

Here's the async/await solution:

async function fetchCompanyProfile(e) {
      let company = '';
      if(e.target.innerHTML){
        company = e.target.innerHTML;
        } else {
        company = e.target.ticker.value;
        } 
      console.log(company)
      e.preventDefault() 
      e.target.reset()
      let companyData = await fetch(https://someapicompany.com/profile/${company}?apikey=xyz)
      setCompany({data: companyData.json()})
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM