处理条件以与 redux 状态管理器反应

handling conditionals in react with a redux state manager

我正在使用 react/redux 从天气 api 构建一个简单的天气检索页面。我的问题是关于处理条件与 redux 状态管理器的反应。我有一个 table 可以在输入城市时显示天气信息。此 table 的 header 在进行查询之前是可见的。我想添加一个条件,将整个 table 替换为告诉用户搜索城市的 div。进行搜索时,我想呈现 table。

我在列表天气容器的渲染方法中设置了一个条件,所以如果没有天气数据显示 div,否则显示 table。我的问题是 table 从不只显示 div。

这让我感到困惑,因为搜索应该更新容器的状态并 re-render 它与数据,不是吗?我猜我需要在我的减速器或状态中添加这个逻辑?我不确定要使用哪个或在哪里放置条件以呈现 div(如果有数据)或 table(如果已进行搜索并且有数据)。

//  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;

更改检查以检查 this.props.weather 的长度是否 > 0。看起来 this.props.weather.data 将永远不存在,因为 this.props.weather 是一个数组:

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>
    );
    }
}