Mike G
Mike G

Reputation: 23

React - Trying to update Fetch call in Parent Component based off of User Input in Child Component

So I am still very much a beginner when it comes to React. I am trying to build an application where the user inputs their location, which would then dynamically update the URL within my fetch call. Based off the results of the fist fetch call, I would then dynamically update a second fetch call, to a different API, providing me with the information needed.

As it stands right now, both Fetch calls are properly working, when provided the right information. The problem I am currently running into is, I don't believe my parent component is re-rendering with the update information. I am trying to console log one of my states but it keeps coming back as blank. The weird part is, the other state that is being created within the child component, is coming back with the right information. Any help would be greatly appreciated!

APP.JS

import Home from './Home/Home';
import Userinput from './UserInput/Userinput';

const url =
    'https://api.openuv.io/api/v1/uv?lat=-33.34&lng=115.342&dt=2018-01-24T10:50:52.283Z';

const url1 = `http://www.mapquestapi.com/geocoding/v1/address?key=${process.env.REACT_APP_MAP_API_KEY}`;

class App extends Component {
    constructor(props) {
        super(props);
        this.state = {
            uvIndex: '',
            lat: '',
            long: '',
            inputValue: '',
        };
        this.handleInputValue = this.handleInputValue.bind(this);
    }
    handleInputValue(val) {
        this.setState({ inputValue: val });
    }

    componentDidMount() {
        let newVal = this.state.inputValue;

        fetch(`${url1}&location=${newVal}`, {
            method: 'GET',
            headers: {
                'content-type': 'application/json',
            },
        })
            .then((res) => res.json())
            .then((res) => {
                this.setState({
                    lat: res.results[0].locations[0].latLng.lat,
                    long: res.results[0].locations[0].latLng.lng,
                });
                // this.setState({ uvIndex: res });
            })
            .catch((err) => {
                console.error(err);
            });

        fetch(url, {
            method: 'GET',
            headers: {
                'content-type': 'application/json',
                'x-access-token': `${process.env.REACT_APP_UV_API_KEY}`,
            },
        })
            .then((res) => res.json())
            .then((res) => {
                console.log(res);
                this.setState({ uvIndex: res });
            })
            .catch((err) => {
                console.error(err);
            });
    }

    render() {
        console.log(this.state.lat); #this state comes back as blank
        console.log(`${url1}&location=${this.state.inputValue}`); # this state comes back with the update userinput 
        return (
            <div>
                <header>
                    <Home />
                </header>
                <div>
                    <Userinput handleInput={this.handleInputValue} />
                </div>
            </div>
        );
    }
}

export default App;

Userinput.js


class Userinput extends Component {
    constructor(props) {
        super(props);
        this.state = {
            inputVal: '',
        };
        this.onInputChange = this.onInputChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
    }

    // handle input change event
    onInputChange(e) {
        this.setState({ inputVal: e.target.value });
    }

    // handle button click event and pass data in parent
    handleSubmit() {
        this.props.handleInput(this.state.inputVal);
    }
    render() {
        return (
            <div>
                <input value={this.state.inputVal} onChange={this.onInputChange} />
                <input type='button' value='Submit' onClick={this.handleSubmit} />
            </div>
        );
    }
}

export default Userinput;

Upvotes: 0

Views: 37

Answers (1)

user12716323
user12716323

Reputation:

Consider this.setState in the App Class. The first fetch() is writing your state like so:

               this.setState({
                    lat: res.results[0].locations[0].latLng.lat,
                    long: res.results[0].locations[0].latLng.lng,
                });

The second fetch() call sets a new state object, which removes the result from the first fetch() call, or whatever fetch() resolves faster:

            .then((res) => {
                console.log(res);
                this.setState({ uvIndex: res });
            })

You can fix this issue with object spread operator:

this.setState({...this.state, uvIndex: res });

This will keep a copy of your state, and only overwrite uvIndex (if it was set before)

Also consider the handleInputVal Method in App.js. I think same problem here. the state is overwritten with a new Object (setState doesn't update the state, it creates a new State), which means that lat and long are being set to undefined 🤔

handleInputValue(val) {
   //this.setState({ inputValue: val }); sets lat and long to undefined
   this.setState({...this.state, inputValue: val }); //keep lat and long values, and update inputValue with val
}

Upvotes: 1

Related Questions