我正在尝试根据本教程https://github.com/reactjs/react-router/tree/master/examples/master-detail向使用redux的应用添加主详细信息,例如https://github.com/bradwestfall/CSS-Tricks-React-Series。
我使用componentWillUpdate获取要更新的组件,但它导致网络错误,因为它不断地反复敲击端点。
我的容器看起来像这样:
import React from 'react';
import { connect } from 'react-redux';
import TeamMemberProfile from '../../views/team-member/team-member-profile';
import TeamMemberList from '../../views/team-member/team-member-list';
import * as teamMemberApi from '../../../api/team-member-api';
import store from '../../../store';
import { loadSearchLayout } from '../../../actions/search-layout-actions';
const TeamMemberProfileContainer = React.createClass({
componentDidMount: function() {
let teamMemberId = this.props.params.teamMemberId;
teamMemberApi.getTeamMembers();
teamMemberApi.getProfile(teamMemberId);
},
componentWillReceiveProps: function(nextProps) {
let teamMemberId = this.props.params.teamMemberId;
let teamMemberProfile = teamMemberApi.getProfileUpdate(teamMemberId);
this.setState({
teamMemberProfile: teamMemberProfile
})
},
// add getProfileUpdate()
render: function() {
return (
<div>
<TeamMemberProfile {...this.props.profile} />
<TeamMemberList teamMembers={this.props.teamMembers} deleteTeamMember={teamMemberApi.deleteTeamMember} />
</div>
);
}
});
const mapStateToProps = function(store) {
return {
profile: store.teamMemberState.teamMemberProfile,
teamMembers: store.teamMemberState.teamMembers
};
};
export default connect(mapStateToProps)(TeamMemberProfileContainer);
我的观点:
// team-member-list.js
import React from 'react';
import { Link } from 'react-router';
// Using "Stateless Functional Components"
export default function(props) {
return (
<div className="data-list">
{props.teamMembers.map(teamMember => {
return (
<div key={teamMember.id} className="container">
<div className="details">
<Link to={'/team-members/' + teamMember.id}>{teamMember.name}</Link>
</div>
<div className="controls">
<button onClick={props.deleteTeamMember.bind(null, teamMember.id)} className="delete">Delete</button>
</div>
</div>
);
})}
</div>
);
}
和
// team-member-profile.js
import React from 'react';
import { Link } from 'react-router';
// Using "Stateless Functional Components"
export default function(props) {
return (
<div className="container">
<img className="col-md-1" src={props.image} />
<div className="details">
<h1>{props.name}</h1>
<p>{props.title}</p>
<p>{props.blurb}</p>
</div>
</div>
);
}
以下是我的行动:
import * as types from '../actions/action-types';
export function getTeamMembersSuccess(teamMembers) {
return {
type: types.GET_TEAM_MEMBERS_SUCCESS,
teamMembers
};
}
export function deleteTeamMemberSuccess(teamMemberId) {
return {
type: types.DELETE_TEAM_MEMBER_SUCCESS,
teamMemberId
};
}
export function teamMemberProfileSuccess(teamMemberProfile) {
return {
type: types.TEAM_MEMBER_PROFILE_SUCCESS,
teamMemberProfile
};
}
export function teamMemberProfileSuccessUpdate(teamMemberProfile) {
return {
type: types.TEAM_MEMBER_PROFILE_SUCCESS_UPDATE,
teamMemberProfileSuccessUpdate
};
}
我的减速机:
import * as types from '../actions/action-types';
import _ from 'lodash';
const initialState = {
teamMembers: [],
teamMemberProfile: {}
};
const teamMemberReducer = function(state = initialState, action) {
switch(action.type) {
case types.GET_TEAM_MEMBERS_SUCCESS:
return Object.assign({}, state, { teamMembers: action.teamMembers });
case types.DELETE_TEAM_MEMBER_SUCCESS:
// Use lodash to create a new teamMember array without the teamMember we want to remove
const newUsers = _.filter(state.teamMembers, teamMember => teamMember.id != action.teamMemberId);
return Object.assign({}, state, { teamMembers: newUsers });
case types.TEAM_MEMBER_PROFILE_SUCCESS:
return Object.assign({}, state, { teamMemberProfile: action.teamMemberProfile });
case types.TEAM_MEMBER_PROFILE_SUCCESS_UPDATE:
return Object.assign({}, state, { teamMemberProfileSuccessUpdate: action.teamMemberProfileSuccessUpdate});
}
return state;
}
export default teamMemberReducer;
API端点:
import axios from 'axios';
import store from '../store';
import { getTeamMembersSuccess, deleteTeamMemberSuccess, teamMemberProfileSuccess, teamMemberProfileSuccessUpdate } from '../actions/team-member-actions';
/**
* Get all teamMembers
*/
export function getTeamMembers() {
return axios.get('http://localhost:3001/team-members')
.then(response => {
store.dispatch(getTeamMembersSuccess(response.data));
return response;
});
}
/**
* Search teamMembers
*/
export function searchTeamMembers(query = '') {
return axios.get('http://localhost:3001/team-members?q='+ query)
.then(response => {
store.dispatch(getTeamMembersSuccess(response.data));
return response;
});
}
/**
* Delete a teamMember
*/
export function deleteTeamMember(teamMemberId) {
return axios.delete('http://localhost:3001/team-members/' + teamMemberId)
.then(response => {
store.dispatch(deleteTeamMemberSuccess(teamMemberId));
return response;
});
}
/**
* getProfile() is much more complex because it has to make
* three XHR requests to get all the profile info.
*/
export function getProfile(teamMemberId) {
// Start with an empty profile object and build it up
// from multiple XHR requests.
let profile = {};
// Get the teamMember data from our local database.
return axios.get('http://localhost:3001/team-members/' + teamMemberId)
.then(response => {
let teamMember = response.data;
profile.name = teamMember.name;
profile.title = teamMember.title;
profile.blurb = teamMember.blurb;
profile.image = teamMember.image;
store.dispatch(teamMemberProfileSuccess(profile));
return;
});
}
export function getProfileUpdate(teamMemberId) {
// Start with an empty profile object and build it up
// from multiple XHR requests.
let profile = {};
// Get the teamMember data from our local database.
return axios.get('http://localhost:3001/team-members/' + teamMemberId)
.then(response => {
let teamMember = response.data;
profile.name = teamMember.name;
profile.title = teamMember.title;
profile.blurb = teamMember.blurb;
profile.image = teamMember.image;
store.dispatch(teamMemberProfileSuccess(profile));
return;
});
}