javascript - 显示旧数据的 Reactjs 组件

标签 javascript reactjs react-redux

我有一个应该显示项目列表的组件。首次加载组件时从 API 获取项目,然后在用户单击按钮时刷新/替换项目。

问题是,我的组件似乎总是落后于用户一步。例如,用户第一次单击按钮时,API 被调用并返回新数据,但组件仍显示它在初始加载时获得的数据。用户第二次点击时,我的组件显示第一次点击时返回的数据。

我的想法是点击按钮后组件重新加载很快,所以当组件显示时状态不会更新,但我不知道如何解决?

我的组件:

import React, {Component} from 'react';
import {connect} from 'react-redux';
import {matchesFetchData} from '../actions/matches';
import Match from './match';


class MatchList extends Component {
    constructor(){
        super();
        this.generateNew = this.generateNew.bind(this);
    }  

    componentDidMount() {
        this.props.fetchData('http://localhost:4752/api/matches');
    }

    render() {
        if (this.props.hasErrored) {
            return <p>Sorry!There was an error loading the items</p>;
        }
        if (this.props.isLoading) {
            return <p>Loading…</p>;
        }

        return (   
            <div>
                <nav className="menu">
                    <input type="number" defaultValue="0" min="0" max="13" ref="safeguards"/>      
                    <button className="generateNew" onClick={this.generateNew}>Ny</button>         
                </nav>
                <ul className="matchlist">
                    {this.props.matches.map(function (match, index) {                        
                        return <Match key={index} match={match}/>
                    }) }
                </ul>
            </div>
        )
    }

    generateNew(e){
        e.preventDefault();
        const value = this.refs.safeguards.value;
        if(value == 0){
            this.props.fetchData('http://localhost:4752/api/matches');
        }
        else{
            this.props.fetchData('http://localhost:4752/api/matches/' + value);
        }
    }
}

const mapStateToProps = (state) => {
    return {
        matches: state.matchesApp.matches,
        hasErrored: state.matchesApp.matchesHasErrored,
        isLoading: state.matchesApp.matchesIsLoading
    };
};


const mapDispatchToProps = (dispatch) => {
    return {
        fetchData: (url) => dispatch(matchesFetchData(url))
    };
};  

export default connect(mapStateToProps, mapDispatchToProps)(MatchList);

Action :

export const MATCHES_HAS_ERRORED = 'MATCHES_HAS_ERRORED';
export const MATCHES_IS_LOADING = 'MATCHES_IS_LOADING';
export const MATCHES_FETCH_DATA_SUCCESS = 'MATCHES_FETCH_DATA_SUCCESS';

export function matchesHasErrored(bool){
    return {
        type: MATCHES_HAS_ERRORED,
        hasErrored: bool
    };
}

export function matchesIsLoading(bool){
    return {
        type: MATCHES_IS_LOADING,
        isLoading: bool
    };
}

export function matchesFetchDataSuccess(matches){
    return{
        type: MATCHES_FETCH_DATA_SUCCESS,
        matches
    };
}

export function matchesFetchData(url){
    return (dispatch) => {
        dispatch(matchesIsLoading(true));

        fetch(url)
        .then((response) => {
            if(!response.ok){
                throw Error(response.statusText);
            }

            dispatch(matchesIsLoading(false));

            return response;
        })
        .then((response) => response.json())
        .then((matches) => dispatch(matchesFetchDataSuccess(matches)))
        .catch(() => dispatch(matchesHasErrored(true)));
    }
}

reducer :

import {MATCHES_HAS_ERRORED, MATCHES_IS_LOADING, MATCHES_FETCH_DATA_SUCCESS} from '../actions/matches';

const initialState = {
    matchesIsLoading: false,
    matchesHasErrored: false,
    matches: []
}

export function matchesApp(state = initialState, action){
    switch(action.type){
      case MATCHES_HAS_ERRORED:
            return Object.assign({}, state, {
                matchesHasErrored: action.hasErrored
            });
      case MATCHES_IS_LOADING:
            return Object.assign({}, state, {
                matchesIsLoading: action.isLoading
            });
      case MATCHES_FETCH_DATA_SUCCESS:
            return Object.assign({}, state, {
                matchesIsLoading: false,
                matchesHasErrored: false,
                matches: action.matches
            });
      default:
            return state;
    }
}

匹配组件:

import React, {Component} from 'react';
import {Link} from 'react-router-dom';
import Result from './result';

class Match extends Component {
    constructor(props){
        super(props);
        this.match = this.props.match;
    }    

    render() {
        return (
            <li>
                <Link to={'/' + this.match.home + '/' + this.match.away}>
                    <span className="matchNumber">{this.match.number}</span>
                    <span className="matchup">
                        {this.match.home} - {this.match.away}
                    </span>
                    <Result value="1" selected={this.match.homeWin} odds={this.match.percent1}/><Result value="X" selected={this.match.draw} odds={this.match.percentX}/><Result value="2" selected={this.match.awayWin} odds={this.match.percent2}/>
                </Link>
            </li>
        )
    }
}

export default Match;

最佳答案

根据组件的外观,有可能是你传下来的key属性有问题,如果display的值来自state,组件就不会被完全移除,从而将显示陈旧数据

关于javascript - 显示旧数据的 Reactjs 组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43762771/

相关文章:

javascript - 在 Redux 中,将数据发布到服务器的最佳方式是什么?

javascript - 是否缓存了 .js 文件?

javascript - 如何在 MVC 中将 dropdownlist 的值传递给 onchange 事件?

reactjs - 使用 React Bootstrap 导航栏

reactjs - React的mouseEvent没有offsetX/offsetY

Redux-thunk 异步操作 : Use custom middleware for async actions

javascript - Redux Form Field Arrays-初始化特定长度的字段数组

javascript - 在 JavaScript 中拆分字符串并检测换行符

javascript - 用鼠标调整大小的 Div 扩展太快

javascript - 触发在焦点事件上调用的异步等待函数的回调