Search code examples
javascriptreactjses6-promise

How do I properly render React components using conditionals if I need to show custom prompt first?


I'm making weather forecast application that needs 2 values (name and city) to render. That's why I want to make a popup appear on site first after loading. Then if user enters proper city - main component appears in place of popup. I wanted to use external library like Sweetalert2 but it doesn't allow double inputs.

I coded this component that uses fetch and conditionals, but it doesn't work. If promise is resolved successfuly it should change state "validation" to trigger rendering another component but when "this.setState({ validation: true })" is present, promise sends "error message" instead of "success" and nothing else happens

import React from 'react'
import App from './App.js';


class InputBox extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            name: "",
            cityValue: "",
            errorMessage: "",
            key: 'x',
            validation: false
        }
        this.handleChange = this.handleChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
    }

    handleChange(event) {
        this.setState({ cityValue: event.target.value })
    }
    handleSubmit(event) {


        fetch('https://api.openweathermap.org/data/2.5/weather?q=' + this.state.cityValue + '&appid=' + this.state.key)
        .then(function (resp) {
            return resp.json()
        })    
        .then(function (data) {
                if (data) {
                   
                      //  this.setState({ validation: true }) // if this is present, there is "error message" in console
                        console.log("success")
                    
                }
            })
            .catch(function () {
                console.log("error message")
                
            });


    }

    render() {
        let content
        if (this.state.validation == false) {
            content = <form
                onSubmit={
                    (e) => {
                        e.preventDefault();
                        this.handleSubmit(this.state.cityValue);
                    }
                }
            >


                <input type="text" value={this.state.cityValue} onChange={this.handleChange} />
                <input type="submit" value="Send" />
            </form>
        } else {
            content = <App city={this.state.cityValue} />
        }

        return (
            <div>
                {content}
            </div>

        );
    }

}

export default InputBox


Solution

  • You can use ternary operator(?:) to achieve conditional rendering

    render() {
        return {this.state.validation == false?(
            <form
                onSubmit={
                    (e) => {
                        e.preventDefault();
                        this.handleSubmit(this.state.cityValue);
                    }
                }
            >
                <input type="text" value={this.state.cityValue} onChange={this.handleChange} />
                <input type="submit" value="Send" />
            </form>):
    
            (<App city={this.state.cityValue} />)
    }}