数据提取

时间:2017-03-03 09:04:50

标签: javascript reactjs redux middleware preloader

我有组件App,它渲染其子节点和Header组件。我使用了来自react-loader repo的Preloader,它带有bool加载并渲染预加载器或页面依赖于bool。当App componentWillMount,通过actionCreators获取数据时,action使用redux-api-middleware,然后在 App 中执行 render 时, Header 通过actionCreator获取数据 boundGetPhotos console screenshot中递归执行 PHOTOS_GET_SUCCESS ,我在 fetchingMiddleware 中记录action.type。所有操作都从我的中间件 fetchingMiddleware 传递到下面。这可能是递归行为的原因,为什么它一次又一次地执行以及我如何解决它

应用

 import React, { Component, PropTypes } from 'react';
 import Counterpart from 'counterpart';
 import { connect } from 'react-redux';
 import Loader from 'react-loader';
 import { bindActionCreators } from 'redux';
 import { getFriends, getMessages } from '../data/Data.Actions';
 import { getUsers } from '../users/Users.Actions';
 import Header from './Header';

class App extends Component {
  componentWillMount() {
    const { boundGetFriends, boundGetMessages, boundGetUsers } = this.props;
    boundGetFriends();
    boundGetMessages();
    boundGetUsers();
  }

  render() {
    const { children, fetching } = this.props;

    return (
      <Loader loaded={!fetching.size}>
        <div>
          <Header/>
          {children}
        </div>
      </Loader>
    );
  }
}

App.propTypes = {
  boundGetUsers: PropTypes.func,
  boundGetMessages: PropTypes.func,
  boundGetFriends: PropTypes.func,
  fetching: PropTypes.array
};

export default connect((store) => {
  return {
    fetching: store.fetching
  };
}, (dispatch) => {
  return {
    boundGetUsers: bindActionCreators(getUsers, dispatch),
    boundGetFriends: bindActionCreators(getMessages, dispatch),
    boundGetMessages: bindActionCreators(getFriends, dispatch)
  };
})(App);

标题

import React, { Component, PropTypes } from 'react';
import React, { Component, PropTypes } from 'react';
import { Navbar, Nav, NavItem, NavDropdown, MenuItem } from 'react-bootstrap';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import ImmutablePropTypes from 'react-immutable-proptypes';
import { getPhotos } from '../user/User.Actions';

class Header extends Component {
  componentWillMount() {
    const { boundGetPhotos } = this.props;
    boundGetPhotos();
  }

  render() {
    return (
      <Navbar fluid collapseOnSelect>
        <Navbar.Brand>
          <a href="/">MyProject</a>
        </Navbar.Brand>
      </Navbar>
    );
  }
}

Header.propTypes = {
  boundGetPhotos: PropTypes.func.isRequired
};

export default connect((store) => null, (dispatch) => {
  return {
    boundGetPhotos: bindActionCreators(getPhotos, dispatch)
  };
})(Header);

FetchingMiddleware

import { startFetching, endFetching } from './FetchingMiddleware.Actions';

export default store => next => action => {
  console.log(action.type);
  if (typeof action !== 'function' && action.type.search(/REQUEST/) !== -1) {
    store.dispatch(startFetching());
  }
  if (typeof action !== 'function' && action.type.search(/SUCCESS|FAILURE/) !== -1) {
    store.dispatch(endFetching());
  }

  next(action);
};

FetchingMiddlewareReducers

import Immutable from 'immutable';
import { END_FETCHING, START_FETCHING, RESET_FETCHING } from './FetchingMiddleware.Actions';
import createReducer from '../utils/utils';

function addFetching(state, action) {
  return state.push(true);
}

function removeFetching(state, action) {
  return state.pop();
}

function resetFetching(state, action) {
  return Immutable.List();
}

export default createReducer({
  [END_FETCHING]: removeFetching,
  [START_FETCHING]: addFetching,
  [RESET_FETCHING]: resetFetching
}, Immutable.List());

FetchingMiddlewareActions

export const END_FETCHING = 'END_FETCHING';
export const START_FETCHING = 'START_FETCHING';
export const RESET_FETCHING = 'RESET_FETCHING';

export function endFetching() {
  return {
    type: END_FETCHING
  };
}

export function startFetching() {
  return {
    type: START_FETCHING
  };
}

export function resetFetching() {
  return {
    type: RESET_FETCHING
  };
}

getPhotos

import { CALL_API } from 'redux-api-middleware';   
export const PHOTOS_GET_SUCCESS = 'PHOTOS_GET_SUCCESS';

export function getPhotos() {
  return {
    [CALL_API]: {
      endpoint: '/photos',
      method: 'GET',
      headers: {
        'Content-Type': 'application/json'
      },
      credentials: 'include',
      types: ['REQUESTPHOTOS', PHOTOS_GET_SUCCESS, 'FAILURE']
    }
  };
}

1 个答案:

答案 0 :(得分:0)

您的<Header />组件应该是一个纯组件,对您的状态容器(Redux)或调度一无所知。

使用此处的方法会使用“连接”来丢弃组件树。并将Redux的意识添加到您的所有组件中。这在可伸缩性方面是不好的做法 - 如果你想用另一个状态容器替换Redux会怎样?

我建议将所有状态和操作绑定到props并将树传递到组件(例如<Header />组件)中。

这也应解决您遇到的问题。

应用

import React, { Component, PropTypes } from 'react';
import Counterpart from 'counterpart';
import { connect } from 'react-redux';
import Loader from 'react-loader';
import { getMasterDataSchema, getMasterDataData } from '../masterdata/MasterData.Actions';
import { getQuestionnaireSchema } from '../questionnaireschema/QuestionnaireSchema.Actions';
import Header from './Header';

class App extends Component {
  componentWillMount() {
    const { 
      GetMasterDataData, 
      GetMasterDataSchema, 
      GetQuestionnaireSchema
    } = this.props;   

    GetMasterDataData();
    GetMasterDataSchema();
    GetQuestionnaireSchema();
  }

  render() {
    const { children, fetching, GetPrincipal } = this.props;

    return (
      <Loader loaded={!fetching.size}>
        <div>
          <Header GetPrincipal={GetPrincipal} />
          {children}
        </div>
      </Loader>
    );
  }
}

App.propTypes = {
  GetPrincipal: PropTypes.func, 
  GetQuestionnaireSchema: PropTypes.func,
  GetMasterDataSchema: PropTypes.func,
  GetMasterDataData: PropTypes.func,
  fetching: PropTypes.array
};

export default connect(({ fetching }) => ({
    fetching
}), {
  GetPrincipal,
  GetQuestionnaireSchema,
  GetMasterDataData,
  GetMasterDataSchema,
})(App);

标题

import React, { Component, PropTypes } from 'react';
import { Navbar, Nav, NavItem, NavDropdown, MenuItem } from 'react-bootstrap';

export default class Header extends Component {
  componentWillMount() {
    const { GetPrincipal } = this.props;
    GetPrincipal();
  }

  render() {
    return (
      <Navbar fluid collapseOnSelect>
        <Navbar.Brand>
          <a href="/">EMS</a>
        </Navbar.Brand>
      </Navbar>
    );
  }
}

Header.propTypes = {
  GetPrincipal: PropTypes.func.isRequired
};