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.