【发布时间】:2016-10-28 09:09:56
【问题描述】:
我这几天一直在寻找答案,这真的很令人沮丧。我最近才开始学习 React,遇到了这个麻烦: 我有一个项目reducer,它是这个(projectReducers.js):
const projectReducer = (state = {
fetching: false,
fetched: false,
item: {},
items: []
}, action) =>
{
switch(action.type){
case 'GET_PROJECT_START':{
state = { ...state, fetching: true};
}
break;
case 'GET_PROJECT_RECEIVED':{
state = {...state, fetching: false, fetched: true, item: action.payload };
}
break;
case 'GET_PROJECT_ERROR':{
state = { ...state, fetching: false, error: action.payload };
}
case 'GET_PROJECTS_START':{
state = { ...state, fetching: true};
}
break;
case 'GET_PROJECTS_RECEIVED':{
state = {...state, fetching: false, fetched: true, items: action.payload };
}
break;
case 'GET_PROJECTS_ERROR':{
state = { ...state, fetching: false, error: action.payload };
}
}
return state
};
export default projectReducer;
附:我知道 GET_PROJECT_START 和 GET_PROJECTS_START 的作用相同,我暂时将它们分开只是为了我自己清楚。
动作(projectActions.js):
export function createProject(number){
return {
type: 'CREATE_PROJECT',
payload: number
}
};
export function getProjectStart(){
return {
type: 'GET_PROJECT_START'
}
};
export function getProjectReceived(project){
return {
type: 'GET_PROJECT_RECEIVED',
payload: project
}
};
export function getProjectError(err){
return {
type: 'GET_PROJECT_ERROR',
payload: err
}
};
export function getProjectsStart(){
return {
type: 'GET_PROJECTS_START'
}
};
export function getProjectsReceived(projects){
return {
type: 'GET_PROJECTS_RECEIVED',
payload: projects
}
};
export function getProjectsError(err){
return {
type: 'GET_PROJECTS_ERROR',
payload: err
}
};
我将我的 reducer 与 combineReducers 组合并创建 store (store.js):
import {createStore, combineReducers, applyMiddleware} from 'redux';
import logger from 'redux-logger';
import mathReducer from './reducers/mathReducer'; //not relevant
import userReducer from './reducers/userReducer'; //not relevant
import projectReducer from './reducers/projectReducer';
export default createStore(
combineReducers({mathReducer, userReducer, projectReducer}),
{},
applyMiddleware(logger()) <- log changes
);
从 react-redux 将根组件包装在 Provider 中以绑定存储(Index.js)
render(
<Provider store={store}>
<App/>
</Provider>,
window.document.getElementById('app')
);
并使用 connect (App.js) 将 store 绑定到 root app props
class App extends React.Component {
render() {
return (
<Router history={browserHistory}>
<Route path="/login" component={Login}/>
<Route path="/" component={Dashboard}>
<IndexRoute component={Home}/>
<Route path="/home" component={Home}/>
<Route path="/blank" project={this.props.project} projectActions={this.props.projectActions} component={Projects}/>
</Route>
</Router>
)
}
}
const mapStateToProps = (state) => {
return {
math: state.mathReducer,
user: state.userReducer,
project: state.projectReducer
};
};
const mapDispatchToProps = (dispatch) => {
return {
projectActions :{
getProjectStart: () => {dispatch(getProjectStart())},
getProjectReceived: (project) => {dispatch(getProjectReceived(project))},
getProjectError: (err) => {dispatch(getProjectError(err))},
getProjectsStart: () => {dispatch(getProjectsStart())},
getProjectsReceived: (project) => {dispatch(getProjectsReceived(project))},
getProjectsError: (err) => {dispatch(getProjectsError(err))}
}
};
};
export default connect(mapStateToProps, mapDispatchToProps)(App);
然后使用(Projects.js)中传递的道具从服务器获取:
export default class Projects extends React.Component {
fetchProjects() {
let projectActions = this.props.route.projectActions;
projectActions.getProjectsStart();
console.log(this.props.route.project);
fetch('http://localhost:3000/projects/').then((response)=> {
setTimeout(() => {
projectActions.getProjectsReceived(response.json());
console.log(this.props.route.project);
}, 5000);
})
}
componentWillMount() {
this.fetchProjects();
}
render() {
return (
<div>
<div className="row">
<h1>Projects</h1>
{this.props.route.project.fetching ? <span> receiving data</span> : <span> Not receiving data </span>}
</div>
</div>
)
}
}
这里发生了有趣的事情,this.props.route.project 永远不会更新 span->即使我添加了 5 秒的巨大延迟,也不会接收数据永远不会改变。然而显示 (prev state | action | next state) 的 redux-logger 显示了所有正确的更改。我的绑定哪里出错了?
【问题讨论】:
-
在我的情况下起作用的是,在 React 路由器中添加了调度程序 onEnter。为此,您将需要 redux-thunk,github.com/gaearon/redux-thunk。
-
现在我完全搞砸了:D 为什么如果我使用你的方法,通过添加 onEnter={this.fetchProjects} 它可以正确获取它们,为什么我不能将调度程序作为属性传递? :D 因为如果我使用 onEnter 我必须将它们添加到 nextState 并且据我所知它们应该作为属性传递,因为状态已经由 redux store 管理:)
-
然而,如果我在父组件中执行获取,子组件仍然没有得到更新:/
-
好的,现在我将连接移动到子组件,一切似乎都可以正常工作,但这要求每个需要访问存储对象或调度程序的组件都应该与 react-redux 连接? :)
-
是的,完全正确。管理起来有点棘手,但效果很好。
标签: javascript reactjs redux react-redux