简体   繁体   中英

How to refresh onscreen data from state change in react and redux

I wonder if anyone can help? I'm new to React and Redux, I have a small site that lists 'Incidents' you then pick an incident and it returns the incident information and a list of responders attending the incident. There are two buttons one that says that I am going to the incident and one that says I am not. I have all of this working (quite chuffed) but when I change my status from 'going' to 'not' or vice versa the list of responders stays static till I refresh the page.

I want list of responders to refresh and show my response.

The Responders are a state that is managed by the reducer and the action makes an API call to another system. I also have Redux-Thunk in the equation as well.

I'm sure I'm missing something incredibly easy but for the life of me I can seem to get this to work.

My Incident Show Page

import React, {PropTypes} from 'react';
import {connect}          from 'react-redux';
import {Link}             from 'react-router';
import {loadIncident, loadResponders, setResponse, theResponse} from '../actions/incidentActions';
import RespondersList  from './responders_list';
class IncidentShow extends React.Component {
    componentWillMount() {
        this.props.loadIncident(this.props.params.id);
        this.props.loadResponders(this.props.params.id);
    }
    renderIncident() {
        if (this.props.incident == null) {
            return (<div>Loading</div>)
        }
        const incident = this.props.incident;
            return (
                <div>{incident.Title}</div>
            );
    }
    renderResponse(){
        if (this.props.responded == null) {
            return (<div>Loading</div>)
        }
        const responded = this.props.responded;
        return (
            <div>{responded.responded}</div>
        );
    }
    setResponse(e) {
        // console.log('Oi!!');
        const id = this.props.params.id;
        const teamUserId = 1; //Team Site user ID
        const message = '';
        const phone = '079000000';
        const arm = '207';
        const response = e.target.value;
        this.props.setResponse(id, response, teamUserId,message,phone,arm);
        this.props.theResponse(response);
    }
    render() {
        return (
            <div className="row">
            <div className="card">
                <div className="card-content">
                    <div className="card-title">Incident</div>
                    {this.renderIncident()}
                </div>
                <div className="card-action no-pad row">
                    <div className="card-title center-align">
                        Please respond
                    </div>
                    <div id="response" className="response" onChange={this.setResponse.bind(this)}>
                        <div className="col m6">
                            <label className="yes">
                                <input type="radio" value="Yes" name="response"/><span>Going</span>
                            </label>
                        </div>
                        <div className="col m6">
                            <label className="no">
                                <input type="radio" value="No" name="response"/><span>Not Going</span>
                            </label>
                        </div>
                    </div>
                    <div className="col s12 center-align">
                        You responded: {this.renderResponse()}
                    </div>
                </div>
            </div>
                <div className="card">
                    <div className="card-content">
                        <div className="card-title">Responders</div>
                        <RespondersList />
                    </div>
                </div>
            </div>
        )
    }
}
function mapStateToProps(state) {
    // console.log('show', state);
    return {
        incident:   state.incident.incident,
        responders: state.responders.responders,
        response:   state.response,
        responded:  state.responded
    };
}
export default connect(mapStateToProps, {loadIncident, loadResponders, setResponse, theResponse})(IncidentShow);

I have tried moving my list of responders to their own page and even made them a class, clutching at straws now...

import React, {Component} from 'react';
import {connect}          from 'react-redux';
// import {loadResponders}   from '../actions/incidentActions';
class RespondersList extends Component {
    // componentWillUpdate() {
    //     this.props.loadResponders(4);
    // }
    render() {
        if (this.props.responders == null) {
            return (<div>Loading</div>)
        }
        const responders = this.props.responders.map((responder) => {
            return (
                <li className="collection-item" key={responder.ID}>
                    <span className="right">{responder.Phone}</span>
                    {responder.Name}
                </li>
            )
        });
        return (
            <ul className="collection">
                {responders}
            </ul>
        );
    }
}
function mapStateToProps(state) {
    // console.log('show', state);
    return {
        responders: state.responders.responders,
    };
}
export default connect(mapStateToProps)(RespondersList);

and this is my actions page

import * as types from './actionTypes';
import incidentApi from '../api/incidentApi';
export function loadIncidentsSuccess(incidents) {
    // console.log('from Action',incidents);
    return {
        type: types.LOAD_INCIDENTS_SUCCESS,
        payload: incidents
    };
}
export function loadIncidentSuccess(incident) {
    // console.log('from Action', incident);
    return {
        type: types.LOAD_INCIDENT_SUCCESS,
        payload: incident
    };
}
export function loadRespondersSuccess(responders) {
    //console.log('from Action', responders);
    return {
        type: types.LOAD_RESPONDERS_SUCCESS,
        payload: responders
    };
}
export function loadResponseSuccess(response) {
    // console.log('from Action', response);
    return {
        type: types.LOAD_RESPONSE_SUCCESS,
        payload: response
    };
}
export function loadTheResponseSuccess(response) {
   // console.log('from Action', response);
    return {
        type: types.LOAD_THE_RESPONSE_SUCCESS,
        payload: response
    };
}
export function loadIncidents() {
    return function (dispatch) {
        return incidentApi.fetchIncidents()
            .then(incidents => {
                // console.log(incidents);
                dispatch(loadIncidentsSuccess(incidents));
            })
            .catch(error => {
                throw(error);
            });
    };
}
export function loadIncident(id) {
    return function (dispatch) {
        return incidentApi.fetchIncident(id)
            .then(incident => {
                // console.log(incidents);
                dispatch(loadIncidentSuccess(incident));
            })
            .catch(error => {
                throw(error);
            });
    };
}
export function loadResponders(id) {
    return function (dispatch) {
        return incidentApi.fetchResponders(id)
            .then(responders => {
                // console.log(incidents);
                dispatch(loadRespondersSuccess(responders));
            })
            .catch(error => {
                throw(error);
            });
    };
}
export function setResponse(id, response, teamUserId, message, phone, arm) {
    return function (dispatch) {
        return incidentApi.setResponse(id, response, teamUserId, message, phone, arm)
            .then(response => {
                // console.log('action',response);
                dispatch(loadResponseSuccess(response));
            })
            .catch(error => {
                throw(error);
            });
    };
}
export function theResponse(response){
    console.log('action', response);
    return function (dispatch){
        return dispatch(loadTheResponseSuccess(response));
    }
}

and finally my responder reducer

import * as types from '../actions/actionTypes';


export default function responseReducer(state = {
    response:  null,
    responded: null,
    responders: []
}, action) {
    switch (action.type) {

        case types.LOAD_THE_RESPONSE_SUCCESS:
            console.log(state);
            return {
                ...state,
                responded: action.payload
            };
        case types.LOAD_RESPONSE_SUCCESS:
            // console.log(state);
            return {
                ...state,
                response: action.payload
            };
        case types.LOAD_RESPONDERS_SUCCESS:
            return {
                ...state,
                responders: action.payload
            };
        default:
            return state;
    }
}

Please be gentle.

Mick

Ok i have found a solution/work around by dispatching the loadResponders action after dispatching the loadResponseSuccess. so my setResponse action now looks like this.

export function setResponse(id, response, teamUserId, message, phone, arm) {
    return function (dispatch) {
        return incidentApi.setResponse(id, response, teamUserId, message, phone, arm)
            .then(response => {
                console.log('action',id);
                dispatch(loadResponseSuccess(response));
                dispatch(loadResponders(id)); //***added this dispatch.
            })
            .catch(error => {
                throw(error);
            });
    };
}

cheers anyway

Mick

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