Javascript React-Axios承诺挂起值未定义

Javascript React-Axios承诺挂起值未定义,javascript,reactjs,webpack,axios,autosuggest,Javascript,Reactjs,Webpack,Axios,Autosuggest,我正在尝试使用React、React autosuggest构建一个天气应用程序,用于下拉列表列出可用城市和api获取Axios App.jsx import React, { Component } from "react"; import CityWeather from './components/CityWeather'; import SearchWeather from './components/SearchWeather'; class App extends Compo

我正在尝试使用React、React autosuggest构建一个天气应用程序,用于下拉列表列出可用城市和api获取Axios

App.jsx

import React, { Component } from "react";
import CityWeather from './components/CityWeather';
import SearchWeather from './components/SearchWeather';




class App extends Component {

    constructor(props){
        super(props);
        this.state = {
            value: '',
            suggestedCities: [],
            cityWeatherData: [],
            currentWeather: [],
        }
    };

    handleCityWeatherData = (city) => {
        this.setState({
            cityWeatherData: city
        });
    };

    handleOnChange = (newValue) => {
        this.setState({
            value: newValue
        });
    }

    render() {

        // Finally, render it!
        return (
            <div>
                <SearchWeather suggestData={{value: this.state.value, suggestedCities: this.state.suggestedCities}} onSelectCity={this.handleCityWeatherData} onChange={this.handleOnChange}/>
                <CityWeather weatherData={this.state.cityWeatherData}/>
            </div>
        );
    }
}

export default App;
我在获取数据时遇到问题,因此在
SearchWeather.jsx
中,我想使用函数
const cities=api.getCities()
获取城市列表,它从另一个文件
apis.jsx
中检索数据,其中Axios在
getCities
方法下使用。错误发生在
api.getCities
中,在控制台中显示
pending
,我得到了
cities
变量的未定义值。不知道该怎么做,我试图在
api.jsx
中添加
wait
before
getCities
,但什么也没做。我可以使用
fetch
代替
Axios
,但我想使用
Axios
了解更多信息。我确信它必须在
const cities=api.getCities()
中执行,但不确定如何执行,我认为我需要使用resolve,但不知道如何执行。新的反应,所以我肯定我错过了一些东西。谢谢你的帮助

SearchWeather.jsx

import React, { Component } from "react";
import Axios from "axios";
import Autosuggest from 'react-autosuggest';
import apis from '../utils/apis';


const getSuggestions = (value) => {
    const inputValue = value.trim().toLowerCase();
    const inputLength = inputValue.length;


    const cities = apis.getCities().then((data) => {
        console.log(data);
        data;
    });

    console.log('calling from getSuggestions');
    console.log(cities); //this is undefined from const cities


    return inputLength === 0 ? [] : cities.filter(city =>

        city.name.toLowerCase().slice(0, inputLength) === inputValue
    );
};

// When suggestion is clicked, Autosuggest needs to populate the input
// based on the clicked suggestion. Teach Autosuggest how to calculate the
// input value for every given suggestion.
const getSuggestionValue = suggestion => suggestion.name;

// Use your imagination to render suggestions.
const renderSuggestion = suggestion => (
  <span>{suggestion.name}</span>
);

class SearchWeather extends Component {

    onChange = (event, { newValue }) => {
        this.props.onChange(newValue);
    };

    // Autosuggest will call this function every time you need to update suggestions.
    // You already implemented this logic above, so just use it.
    onSuggestionsFetchRequested = ({ value }) => {
        this.setState({
          suggestedCities: getSuggestions(value)
        });
    };

    // Autosuggest will call this function every time you need to clear suggestions.
    onSuggestionsClearRequested = () => {
        this.setState({
          suggestedCities: []
        });
    };

    renderSuggestionsContainer = ({ containerProps, children, query }) => {
        return (
            <div {...containerProps}>
                {children}
                <h5>I like showing up.</h5>
            </div>
        );
    };

    fetchCityWeather = (cityId) => {
        //fetching sample request
        Axios.get("/public/sampleWeather.json").then((response) => {
            if(response.status === 200){
                return response.data
            }
            else{
                console.log('fetchCityWeather - something went wrong');
            }

        })
        .catch((error) => {
            console.log(error);
        });
    };

    onSuggestionSelected = (event, { suggestion, suggestionValue, suggestionIndex, sectionIndex, method }) => {
        console.log(suggestion);
        console.log(method);

        if(method == 'click'){
            let cityId = suggestion.id;
            let data = this.fetchCityWeather(cityId);
            this.props.onSelectCity(data); //pass data to parent
        }
    };


    componentDidMount = () => {
        console.log('componentDidMount');
    }


    render(){
        const value = this.props.suggestData.value;
        const suggestedCities = this.props.suggestData.suggestedCities;

        // Autosuggest InputProps
        const inputProps = {
          placeholder: 'Type your city',
          value,
          onChange: this.onChange
        };

        return(
            <Autosuggest
                suggestions={suggestedCities}
                onSuggestionsFetchRequested={this.onSuggestionsFetchRequested}
                onSuggestionsClearRequested={this.onSuggestionsClearRequested}
                getSuggestionValue={getSuggestionValue}
                renderSuggestion={renderSuggestion}
                inputProps={inputProps} 
                shouldRenderSuggestions = {(v) => v.trim().length > 0}
                renderSuggestionsContainer={this.renderSuggestionsContainer}
                onSuggestionSelected={this.onSuggestionSelected}
            />
        );
    }
}

export default SearchWeather;
const getSuggestions = (value, cb) => {
/**/
    apis.getCities().then(cities => {
       /* your logic to filter cities goes here */

       // return your filtered cities here 
       return cb(filteredCities)
    });
}

class SearchWeather extends Component{
/**/
    onSuggestionsFetchRequested = ({ value }) => {
        const cb = suggestedCities => this.setState({ suggestedCities })

        return getSuggestions(value, cb)
    };
/**/
}
我注意到控制台中的顺序如下:

SearchWeather中的
console.log(城市)

Promise{}

来自
api.jsx
console.log(“来自API”,res.data.cities),数据

来自API(4)[{..},{..}]

SearchWeather
console.log(“来自getCities”,数据)

来自getCities(4)[{..},{..}]


不知道这是否有帮助,但是跳过了
const cities
,然后返回并打印实际数据Axios无法像
let cities=“/public/cities.json”那样请求URL

如果你把这个json文件放在公共文件夹中,你可以像

http://localhost:3001/public/cities.json


别忘了港口。这是对主机的HTTP请求,而不仅仅是读取本地文件。

我注意到的第一件事是:

let cities=“/public/cities.json”

为了将文件读入代码,必须使用require,如下所示:

getCities: function(){
   return  Axios.get(cities)
},
let cities=require('./public/cities.json')

或者像ES6一样

import cities from./public/cities.json'

你休息得好就好

我注意到的第二件事是,在第一个承诺得到解决后,您将返回Axios(在该承诺中,您根本不返回任何东西)。你可以这样做:

getCities: function(){
   return  Axios.get(cities)
},
或者这个:

    getCities: function(){
        return  Axios.get(cities).then(res => res.data.cities).catch(...) // return cities
    },
为什么会这样

因为在用
.then
函数将其包装后,您正在解析它,而它在该函数中返回的任何内容都将成为另一个承诺,允许您将其与另一个then链接,或者在您的情况下,将其链接为:

apis.getCities().then((data) => {
    const cities = data
});
如果使用我编写的第一个函数,您将在这个函数的data参数中得到响应。第二种方法可以让你直接进入数据

编辑:

由于我误读了代码,并且我的答案没有任何意义,我正在编辑我的答案:

为了从异步承诺中获得响应,必须向函数传递回调(或异步/等待),如下所示:

getCities: function(){
   return  Axios.get(cities)
},
api.jsx

import Axios from "axios";

//local file
let cities = "./public/cities.json";


export default {
    getCities: function(){
        return  Axios.get(cities).then((res) => {
            console.log("from apis", res.data.cities);
            resolve(res.data.cities);
        }).catch((error) => {
            console.log("from apis.jsx", error);
            []
        });
    },
    getTest: function(){
        return 'hello';
    }
    //add api for weather
};
/**/
    getCities : cb => Axios.get(cities).then(res => cb(res.data.cities))
/**/
SearchWeather.jsx

import React, { Component } from "react";
import Axios from "axios";
import Autosuggest from 'react-autosuggest';
import apis from '../utils/apis';


const getSuggestions = (value) => {
    const inputValue = value.trim().toLowerCase();
    const inputLength = inputValue.length;


    const cities = apis.getCities().then((data) => {
        console.log(data);
        data;
    });

    console.log('calling from getSuggestions');
    console.log(cities); //this is undefined from const cities


    return inputLength === 0 ? [] : cities.filter(city =>

        city.name.toLowerCase().slice(0, inputLength) === inputValue
    );
};

// When suggestion is clicked, Autosuggest needs to populate the input
// based on the clicked suggestion. Teach Autosuggest how to calculate the
// input value for every given suggestion.
const getSuggestionValue = suggestion => suggestion.name;

// Use your imagination to render suggestions.
const renderSuggestion = suggestion => (
  <span>{suggestion.name}</span>
);

class SearchWeather extends Component {

    onChange = (event, { newValue }) => {
        this.props.onChange(newValue);
    };

    // Autosuggest will call this function every time you need to update suggestions.
    // You already implemented this logic above, so just use it.
    onSuggestionsFetchRequested = ({ value }) => {
        this.setState({
          suggestedCities: getSuggestions(value)
        });
    };

    // Autosuggest will call this function every time you need to clear suggestions.
    onSuggestionsClearRequested = () => {
        this.setState({
          suggestedCities: []
        });
    };

    renderSuggestionsContainer = ({ containerProps, children, query }) => {
        return (
            <div {...containerProps}>
                {children}
                <h5>I like showing up.</h5>
            </div>
        );
    };

    fetchCityWeather = (cityId) => {
        //fetching sample request
        Axios.get("/public/sampleWeather.json").then((response) => {
            if(response.status === 200){
                return response.data
            }
            else{
                console.log('fetchCityWeather - something went wrong');
            }

        })
        .catch((error) => {
            console.log(error);
        });
    };

    onSuggestionSelected = (event, { suggestion, suggestionValue, suggestionIndex, sectionIndex, method }) => {
        console.log(suggestion);
        console.log(method);

        if(method == 'click'){
            let cityId = suggestion.id;
            let data = this.fetchCityWeather(cityId);
            this.props.onSelectCity(data); //pass data to parent
        }
    };


    componentDidMount = () => {
        console.log('componentDidMount');
    }


    render(){
        const value = this.props.suggestData.value;
        const suggestedCities = this.props.suggestData.suggestedCities;

        // Autosuggest InputProps
        const inputProps = {
          placeholder: 'Type your city',
          value,
          onChange: this.onChange
        };

        return(
            <Autosuggest
                suggestions={suggestedCities}
                onSuggestionsFetchRequested={this.onSuggestionsFetchRequested}
                onSuggestionsClearRequested={this.onSuggestionsClearRequested}
                getSuggestionValue={getSuggestionValue}
                renderSuggestion={renderSuggestion}
                inputProps={inputProps} 
                shouldRenderSuggestions = {(v) => v.trim().length > 0}
                renderSuggestionsContainer={this.renderSuggestionsContainer}
                onSuggestionSelected={this.onSuggestionSelected}
            />
        );
    }
}

export default SearchWeather;
const getSuggestions = (value, cb) => {
/**/
    apis.getCities().then(cities => {
       /* your logic to filter cities goes here */

       // return your filtered cities here 
       return cb(filteredCities)
    });
}

class SearchWeather extends Component{
/**/
    onSuggestionsFetchRequested = ({ value }) => {
        const cb = suggestedCities => this.setState({ suggestedCities })

        return getSuggestions(value, cb)
    };
/**/
}

cb
(或回调)将在解决承诺后触发。

这听起来更像@SungKim我在以React.js开头时也有类似的错误,因此我认为这种方法可以解决Axios能够读取它,因为文件位于构建文件夹中。Xios能够读取文件,而无需
require
,该文件存在于生成文件夹中。我尝试了第一种方法,但仍然没有得到承诺。那么,
const cities
应该是什么呢<代码>const cities=api.getCities()?如果使用第二种方法,那么函数中的
cb
是什么?我正在修正我的答案,因为我误读了你的代码。实际上,cb最初应该是一个回调,因为为了检索承诺的结果(而不是异步/等待),它使用回调。