简体   繁体   中英

handling conditionals in react with a redux state manager

I am using react/redux to build a simple weather retrieval page from a weather api. My question is about handling conditionals in react with a redux state manager. I have a table that displays weather information when a city is entered. The header for this table is visible before the query is made. I want to add a conditional to replace the whole table with a div that tells the user to search for a city. When a search is made I want to render the table.

I made a conditional inside the render method of the list weather container so if there is no weather data display the div else display the table. My problem is the table never displays only the div.

This confuses me because a search should update the state of the container and re-render it with the data, no? I'm guessing that I need to add this logic in my reducer or state? I'm not sure which to use or where to place the conditional to render a div if there is data or the table if a search has been made and there is data.

//  search container
class SearchBar extends Component {
constructor(props) {
    super(props);

    this.state = { term: '' };
    this.onInputChange = this.onInputChange.bind(this);
    this.onFormSubmit = this.onFormSubmit.bind(this);
}

onInputChange(event) {
   this.setState({ term: event.target.value });
}

onFormSubmit(event) {
    event.preventDefault();
    this.props.fetchWeather(this.state.term);
    this.setState({ term : ''});
}

render() {
    return (
        <form onSubmit={this.onFormSubmit}
                className={styles.search}>
            <div className={styles.wrap}>
                <input  value={ this.state.term }
                        onChange={ this.onInputChange }
                        placeholder="Enter US cities for a forecast"
                        className={styles.wrap__input}/>
                <button type="submit" className={styles.wrap__btn}>search</button>
            </div>     
        </form>
    )
  }
}

function MapDispatchToProps(dispatch) {
return bindActionCreators({ fetchWeather }, dispatch);
}

export default connect(null, MapDispatchToProps)(SearchBar);


// weather list container
class ListWeather extends Component {
renderWeather(data){

if(!data) {
    let id = Math.round(Math.random() * 100);
    return  (
        <tr key={ id }>
            <td className={styles.table__data_error} colspan="5">Please enter a valid US City.</td>
        </tr>
    )
} else  {
    const temps = data.list.map(weather => weather.main.temp * 9/5 - 459.67);
    const pressures = data.list.map(weather => weather.main.pressure);
    const humidities = data.list.map(weather => weather.main.humidity);
    const avg = "AVG";

        return (
            <tr key={ data.city.id }>
                <td className={styles.table__data_name}>{ data.city.name }</td>
                <td><Chart color="red" data={temps} />{avg} Temperature</td>
                <td><Chart color="green" data={humidities} />{avg} Humidity</td>
                <td><Chart color="blue" data={pressures} />{avg} Pressure</td>
            </tr>
        )
    }
}

render(){

    if(!this.props.weather.data) {
        return (
            <div className={styles.start}>Enter a US City to get started.</div>
        )
    } else {
    return (
        <table className={styles.table}>
        <thead className={styles.table__head}>
            <tr className={styles.table__row}>
                <th className={styles.table__rowhead}>City</th>
                <th className={styles.table__rowhead}>Temp</th>
                <th className={styles.table__rowhead}>Humidity</th>
                <th className={styles.table__rowhead}>Pressure</th>
            </tr>
        </thead>
        <tbody className={styles.table__body}>
            { this.props.weather.map(this.renderWeather)}
        </tbody>
    </table>
    );
    }
}
}

function MapStateToProps({ weather }) {
return { weather }; 
}

export default connect(MapStateToProps)(ListWeather)


// actions / index.js 
import axios from 'axios';

const API_KEY='b60aa70986cac3edb4248b5569b74a92';
const ROOT_URL=`http://api.openweathermap.org/data/2.5/forecast? 
appid=${API_KEY}`;

export const FETCH_WEATHER = 'FETCH_WEATHER';

export function fetchWeather(city) {
const url = `${ROOT_URL}&q=${city},us`;
const request = axios.get(url);

return {
    type: FETCH_WEATHER,
    payload: request
};
}

// reducers/reducer_weather.js
import { FETCH_WEATHER } from '../actions/index';

export default function(state=[], action) {
switch (action.type) {
    case FETCH_WEATHER:
        // return state.concat([ action.payload.data ]);
        return [ action.payload.data, ...state ]
    default : return state;
}
return state;
}

//reducers/index.js
import { combineReducers } from 'redux';
import WeatherReducer from './reducer_weather';

const rootReducer = combineReducers({
weather: WeatherReducer
});

export default rootReducer;

Change your check to check if this.props.weather has a length > 0. Looks like this.props.weather.data will never exist since this.props.weather is an array:

render(){

    if(!this.props.weather.length) {
        return (
            <div className={styles.start}>Enter a US City to get started.</div>
        )
    } else {
    return (
        <table className={styles.table}>
        <thead className={styles.table__head}>
            <tr className={styles.table__row}>
                <th className={styles.table__rowhead}>City</th>
                <th className={styles.table__rowhead}>Temp</th>
                <th className={styles.table__rowhead}>Humidity</th>
                <th className={styles.table__rowhead}>Pressure</th>
            </tr>
        </thead>
        <tbody className={styles.table__body}>
            { this.props.weather.map(this.renderWeather)}
        </tbody>
    </table>
    );
    }
}

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