Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/date/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Reactjs React/Redux-应用程序加载/init时的调度操作_Reactjs_Redux - Fatal编程技术网

Reactjs React/Redux-应用程序加载/init时的调度操作

Reactjs React/Redux-应用程序加载/init时的调度操作,reactjs,redux,Reactjs,Redux,我有来自服务器的令牌身份验证,所以当我的Redux应用程序最初加载时,我需要向该服务器发出请求,以检查用户是否经过身份验证,如果是,我应该获得令牌 我发现不建议使用Redux core INIT actions,所以在呈现应用程序之前,如何分派操作?您可以在RootcomponentDidMount方法中分派操作,在render方法中可以验证身份验证状态 大概是这样的: class App extends Component { componentDidMount() { this.

我有来自服务器的令牌身份验证,所以当我的Redux应用程序最初加载时,我需要向该服务器发出请求,以检查用户是否经过身份验证,如果是,我应该获得令牌


我发现不建议使用Redux core INIT actions,所以在呈现应用程序之前,如何分派操作?

您可以在Root
componentDidMount
方法中分派操作,在
render
方法中可以验证身份验证状态

大概是这样的:

class App extends Component {
  componentDidMount() {
    this.props.getAuth()
  }

  render() {
    return this.props.isReady
      ? <div> ready </div>
      : <div>not ready</div>
  }
}

const mapStateToProps = (state) => ({
  isReady: state.isReady,
})

const mapDispatchToProps = {
  getAuth,
}

export default connect(mapStateToProps, mapDispatchToProps)(App)
class Startup extends Component {
  static propTypes = {
    connection: PropTypes.object
  }
  componentDidMount() {
    this.props.actions.initialiseConnection();
  }
  render() {
    return this.props.connection
      ? this.props.children
      : (<p>Loading...</p>);
  }
}

function mapStateToProps(state) {
  return {
    connection: state.connection
  };
}

function mapDispatchToProps(dispatch) {
  return {
    actions: bindActionCreators(Actions, dispatch)
  };
}

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(Startup);
类应用程序扩展组件{
componentDidMount(){
this.props.getAuth()
}
render(){
归还这个。道具。我准备好了
准备好的
:没有准备好
}
}
常量mapStateToProps=(状态)=>({
已经准备好了,
})
const mapDispatchToProps={
getAuth,
}
导出默认连接(mapStateToProps、mapDispatchToProps)(应用程序)

更新2020: 除了其他解决方案外,我还使用Redux中间件检查每个登录尝试失败的请求:

export default () => next => action => {
  const result = next(action);
  const { type, payload } = result;

  if (type.endsWith('Failure')) {
    if (payload.status === 401) {
      removeToken();

      window.location.replace('/login');
    }
  }

  return result;
};
更新2018:此答案适用于反应路由器3

我用react路由器道具解决了这个问题。这是代码的样子:

//在应用程序开始呈现react route及其任何相关DOM元素之前,此函数只调用一次
//它可用于向应用程序添加初始配置设置
职能部门(调度){
返回(下一个状态、替换、回调)=>{
分派(performTokenRequest())
.然后(()=>{
//回调就像一个“下一个”函数,应用程序初始化将停止,直到调用它为止。
回调();
});
};
}
常量应用=()=>(
);

我对为此提出的任何解决方案都不满意,然后我想到我正在考虑需要呈现的类。如果我刚刚创建了一个用于启动的类,然后将其推入
componentDidMount
方法,然后让
render
显示一个加载屏幕,会怎么样

<Provider store={store}>
  <Startup>
    <Router>
      <Switch>
        <Route exact path='/' component={Homepage} />
      </Switch>
    </Router>
  </Startup>
</Provider>

然后是这样的:

class App extends Component {
  componentDidMount() {
    this.props.getAuth()
  }

  render() {
    return this.props.isReady
      ? <div> ready </div>
      : <div>not ready</div>
  }
}

const mapStateToProps = (state) => ({
  isReady: state.isReady,
})

const mapDispatchToProps = {
  getAuth,
}

export default connect(mapStateToProps, mapDispatchToProps)(App)
class Startup extends Component {
  static propTypes = {
    connection: PropTypes.object
  }
  componentDidMount() {
    this.props.actions.initialiseConnection();
  }
  render() {
    return this.props.connection
      ? this.props.children
      : (<p>Loading...</p>);
  }
}

function mapStateToProps(state) {
  return {
    connection: state.connection
  };
}

function mapDispatchToProps(dispatch) {
  return {
    actions: bindActionCreators(Actions, dispatch)
  };
}

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(Startup);
类启动扩展组件{
静态类型={
连接:PropTypes.object
}
componentDidMount(){
this.props.actions.initialiseConnection();
}
render(){
返回此.props.connection
这是我的道具
:(加载…

); } } 函数MapStateTops(状态){ 返回{ 连接:state.connection }; } 功能图DispatchToprops(调度){ 返回{ 操作:bindActionCreators(操作、调度) }; } 导出默认连接( MapStateTops, mapDispatchToProps )(启动);

然后编写一些redux操作来异步初始化应用程序。使用:Apollo客户端2.0、React路由器v4、React 16(光纤)

所选答案使用旧路由器v3。我需要执行“分派”以加载应用程序的全局设置。诀窍是使用componentWillUpdate,尽管示例使用apollo客户端,但不获取解决方案是等效的。 你不需要一束水

SettingsLoad.js

import React, { Component } from 'react';
import { connect } from 'react-redux';
import {bindActionCreators} from "redux";
import {
  graphql,
  compose,
} from 'react-apollo';

import {appSettingsLoad} from './actions/appActions';
import defQls from './defQls';
import {resolvePathObj} from "./utils/helper";
class SettingsLoad extends Component {

  constructor(props) {
    super(props);
  }

  componentWillMount() { // this give infinite loop or no sense if componente will mount or not, because render is called a lot of times

  }

  //componentWillReceiveProps(newProps) { // this give infinite loop
  componentWillUpdate(newProps) {

    const newrecord = resolvePathObj(newProps, 'getOrgSettings.getOrgSettings.record');
    const oldrecord = resolvePathObj(this.props, 'getOrgSettings.getOrgSettings.record');
    if (newrecord === oldrecord) {
      // when oldrecord (undefined) !== newrecord (string), means ql is loaded, and this will happens
      //  one time, rest of time:
      //     oldrecord (undefined) == newrecord (undefined)  // nothing loaded
      //     oldrecord (string) == newrecord (string)   // ql loaded and present in props
      return false;
    }
    if (typeof newrecord ==='undefined') {
      return false;
    }
    // here will executed one time
    setTimeout(() => {
      this.props.appSettingsLoad( JSON.parse(this.props.getOrgSettings.getOrgSettings.record));
    }, 1000);

  }
  componentDidMount() {
    //console.log('did mount this props', this.props);

  }

  render() {
    const record = resolvePathObj(this.props, 'getOrgSettings.getOrgSettings.record');
    return record
      ? this.props.children
      : (<p>...</p>);
  }
}

const withGraphql = compose(

  graphql(defQls.loadTable, {
    name: 'loadTable',
    options: props => {
      const optionsValues = {  };
      optionsValues.fetchPolicy = 'network-only';
      return optionsValues ;
    },
  }),
)(SettingsLoad);


const mapStateToProps = (state, ownProps) => {
  return {
    myState: state,
  };
};

const mapDispatchToProps = (dispatch) => {
  return bindActionCreators ({appSettingsLoad, dispatch }, dispatch );  // to set this.props.dispatch
};

const ComponentFull = connect(
  mapStateToProps ,
  mapDispatchToProps,
)(withGraphql);

export default ComponentFull;
import React,{Component}来自'React';
从'react redux'导入{connect};
从“redux”导入{bindActionCreators};
进口{
graphql,
组成
}从‘阿波罗反应’;
从“/actions/appActions”导入{appSettingsLoad};
从“/defQls”导入defQls;
从“/utils/helper”导入{ResolvePathBJ}”;
类设置加载扩展组件{
建造师(道具){
超级(道具);
}
componentWillMount(){//这会给出无限循环,或者说对于Component是否装载没有意义,因为render被调用了很多次
}
//componentWillReceiveProps(newProps){//这将给出无限循环
组件将更新(newProps){
const newrecord=resolvephobj(newProps'getOrgSettings.getOrgSettings.record');
const oldrecord=ResolvePathBj(this.props,'getOrgSettings.getOrgSettings.record');
if(newrecord==oldrecord){
//当oldrecord(未定义)!==newrecord(字符串)时,表示加载了ql,这将发生
//一次,其余时间:
//oldrecord(未定义)=newrecord(未定义)//未加载任何内容
//oldrecord(string)=newrecord(string)//ql加载并显示在道具中
返回false;
}
if(typeof newrecord==='undefined'){
返回false;
}
//这里将执行一次
设置超时(()=>{
appsetingsload(JSON.parse(this.props.getOrgSettings.getOrgSettings.record));
}, 1000);
}
componentDidMount(){
//console.log('did mount this props',this.props);
}
render(){
const record=ResolvePathBJ(this.props,'getOrgSettings.getOrgSettings.record');
返回记录
这是我的道具
:(…

); } } 常量withGraphql=compose( graphql(defQls.loadTable{ 名称:'loadTable', 选项:道具=>{ const optionsValues={}; optionsValues.fetchPolicy='仅限网络'; 返回选项值; }, }), )(设置SLOAD); const mapStateToProps=(state,ownProps)=>{ 返回{ 我的国家:国家, }; }; const mapDispatchToProps=(调度)=>{ 返回bindActionCreators({appSettingsLoad,dispatch},dispatch);//设置this.props.dispatch }; const ComponentFull=connect( MapStateTops, mapDispatchToProps, )(使用GraphQL); 导出默认组件full;
App.js

class App extends Component<Props> {
  render() {

    return (
        <ApolloProvider client={client}>
          <Provider store={store} >
            <SettingsLoad>
              <BrowserRouter>
            <Switch>
              <LayoutContainer
                t={t}
                i18n={i18n}
                path="/myaccount"
                component={MyAccount}
                title="form.myAccount"
              />
              <LayoutContainer
                t={t}
                i18n={i18n}
                path="/dashboard"
                component={Dashboard}
                title="menu.dashboard"
              />
类应用程序扩展组件{
render(){
返回(

这里的所有答案似乎都是关于创建根组件并在componentDidMount中启动它的变体。关于redux,我最喜欢的一件事是它将从组件生命周期中提取数据解耦。我看不出有什么原因
import { fork, all } from 'redux-saga/effects';
import launchSaga from './launchSaga';
// ... other saga imports

// Single entry point to start all sagas at once
const root = function* rootSaga() {
  yield all([
    fork( ... )
    // ... other sagas
    fork(launchSaga)
  ]);
};

export default root;
useEffect(() => store.dispatch(handleAppInit()), []);
import React, { useEffect } from 'react';
import { Provider } from 'react-redux';

import AppInitActions from './store/actions/appInit';
import store from './store';

export default function App() {
  useEffect(() => store.dispatch(AppInitActions.handleAppInit()), []);
  return (
    <Provider store={store}>
      <div>
        Hello World
      </div>
    </Provider>
  );
}
import { appPreInit } from '../store/actions';
// app preInit is an action: const appPreInit = () => ({ type: APP_PRE_INIT })
import { useDispatch } from 'react-redux';
export default App() {
    const dispatch = useDispatch();
    // only change the dispatch effect when dispatch has changed, which should be never
    useEffect(() => dispatch(appPreInit()), [ dispatch ]);
    return (<div>---your app here---</div>);
}
class SwitchAccount extends Component {

    constructor(props) {
        super(props);

        this.Format_Account_List = this.Format_Account_List.bind(this); //function to format list for html form drop down

        //Local state
        this.state = {
                formattedUserAccounts : [],  //Accounts list with html formatting for drop down
                selectedUserAccount: [] //selected account by user

        }

    }



    //Check if accounts has been updated by redux thunk and update state
    componentDidUpdate(prevProps) {

        if (prevProps.accounts !== this.props.accounts) {
            this.Format_Account_List(this.props.accounts);
        }
     }


     //take the JSON data and work with it :-)   
     Format_Account_List(json_data){

        let a_users_list = []; //create user array
        for(let i = 0; i < json_data.length; i++) {

            let data = JSON.parse(json_data[i]);
            let s_username = <option key={i} value={data.s_username}>{data.s_username}</option>;
            a_users_list.push(s_username); //object
        }

        this.setState({formattedUserAccounts: a_users_list}); //state for drop down list (html formatted)

    }

     changeAccount() {

         //do some account change checks here
      }

      render() {


        return (
             <Form >
                <Form.Group >
                    <Form.Control onChange={e => this.setState( {selectedUserAccount : e.target.value})} as="select">
                        {this.state.formattedUserAccounts}
                    </Form.Control>
                </Form.Group>
                <Button variant="info" size="lg" onClick={this.changeAccount} block>Select</Button>
            </Form>
          );


         }    
 }

 const mapStateToProps = state => ({
      accounts: state.accountSelection.accounts, //accounts from redux store
 });


  export default connect(mapStateToProps)(SwitchAccount);
React.useEffect(props.dispatchOnAuthListener, []);
function App(props) {
  const [user, setUser] = React.useState(props.authUser);
  React.useEffect(() => setUser(props.authUser), [props.authUser]);
  React.useEffect(props.dispatchOnAuthListener, []);
  return <>{user.loading ? "Loading.." :"Hello! User"}<>;
}

const mapStateToProps = (state) => {
  return {
    authUser: state.authentication,
  };
};

const mapDispatchToProps = (dispatch) => {
  return {
    dispatchOnAuthListener: () => dispatch(registerOnAuthListener()),
  };
};

export default connect(mapStateToProps, mapDispatchToProps)(App);