我该如何解决“动作必须是普通对象。使用自定义中间件执行异步操作。”?

时间:2018-08-03 13:07:02

标签: reactjs react-native redux react-redux fetch

我在react native中遇到了这个问题,但它在react dom中起作用。 另外,除了反应导航中间件,我没有使用中间件,反应导航中间件是集成到redux中的。 我要执行的操作是发送电话和密码以进行操作,该操作将提取令牌并保存到redux存储,之后我也想检索它以进行令牌身份验证

商店

import React from 'react';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';

import AppReducer from './src/reducers';
import { AppNavigator, middleware } from './src/navigators';

const store = createStore(AppReducer, applyMiddleware(middleware));

class App extends React.Component {
  render() {
    return (
      <Provider store={store}>
        <AppNavigator />
      </Provider>
    );
  }
}
export default App;

操作

export const login = (phone, password) => {
  return (dispatch, getState) => {
    let headers = { 'Content-Type': 'application/json' };
    let body = JSON.stringify({ phone, password });

    return fetch('/api/auth/login/', { headers, body, method: 'POST' })
      .then(res => {
        if (res.status < 500) {
          return res.json().then(data => {
            return { status: res.status, data };
          });
        } else {
          console.log('Server Error!');
          throw res;
        }
      })
      .then(res => {
        if (res.status === 200) {
          dispatch({ type: 'LOGIN_SUCCESSFUL', data: res.data });
          return res.data;
        } else if (res.status === 403 || res.status === 401) {
          dispatch({ type: 'AUTHENTICATION_ERROR', data: res.data });
          throw res.data;
        } else {
          dispatch({ type: 'LOGIN_FAILED', data: res.data });
          throw res.data;
        }
      });
  };
};

减速器

import { combineReducers } from 'redux';
import { NavigationActions } from 'react-navigation';

import { RootNavigator } from '../navigators';

// Start with two routes: The Main screen, with the Login screen on top.
const firstAction = RootNavigator.router.getActionForPathAndParams('Main');
const tempNavState = RootNavigator.router.getStateForAction(firstAction);
const secondAction = RootNavigator.router.getActionForPathAndParams('Login');
const initialNavState = RootNavigator.router.getStateForAction(
  secondAction,
  tempNavState
);

function nav(state = initialNavState, action) {
  let nextState;
  switch (action.type) {
    case 'Login':
      nextState = RootNavigator.router.getStateForAction(
        NavigationActions.back(),
        state
      );
      break;
    case 'Logout':
      nextState = RootNavigator.router.getStateForAction(
        NavigationActions.navigate({ routeName: 'Login' }),
        state
      );
      break;
    default:
      nextState = RootNavigator.router.getStateForAction(action, state);
      break;
  }

  // Simply return the original `state` if `nextState` is null or undefined.
  return nextState || state;
}

const initialAuthState = {
  token: null,
  isAuthenticated: null,
  isLoading: true,
  user: null,
  errors: {}
};

function auth(state = initialAuthState, action) {
  switch (action.type) {
    case 'USER_LOADING':
      return { ...state, isLoading: true };

    case 'USER_LOADED':
      return {
        ...state,
        isAuthenticated: true,
        isLoading: false,
        user: action.user
      };

    case 'LOGIN_SUCCESSFUL':
    case 'REGISTRATION_SUCCESSFUL':
      return {
        ...state,
        token: action.token,
        ...action.data,
        isAuthenticated: true,
        isLoading: false,
        errors: null
      };

    case 'AUTHENTICATION_ERROR':
    case 'LOGIN_FAILED':
    case 'REGISTRATION_FAILED':
    case 'LOGOUT_SUCCESSFUL':
      return {
        ...state,
        errors: action.data,
        token: null,
        user: null,
        isAuthenticated: false,
        isLoading: false
      };

    case 'Login':
      return { ...state, isLoggedIn: true };
    case 'Logout':
      return { ...state, isLoggedIn: false };
    default:
      return state;
  }
}

const AppReducer = combineReducers({
  nav,
  auth
});

export default AppReducer;

登录页面

import React, { Component } from 'react';
import { Button, StyleSheet, Text, View, TextInput } from 'react-native';
import { connect } from 'react-redux';

import { login } from '../actions/auth';

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF'
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10
  }
});

class LoginPage extends Component {
  state = {
    phone: '',
    password: ''
  };
  render() {
    console.log(this.state.phone);
    return (
      <View style={styles.container}>
        <TextInput
          style={{ height: 40, width: 100 }}
          placeholder="Enter phone number"
          onChangeText={text => this.setState({ phone: text })}
          value={this.state.phone}
        />
        <TextInput
          style={{ height: 40, width: 100 }}
          placeholder="Enter passoword"
          onChangeText={text => this.setState({ password: text })}
          value={this.state.password}
        />
        {this.props.errors.length > 0 &&
          this.props.errors.map(error => (
            <Text key={error.field}>{error.message}</Text>
          ))}
        <Button
          onPress={() =>
            this.props.login(this.state.phone, this.state.password)
          }
          title="Log in"
        />
      </View>
    );
  }
}

LoginPage.navigationOptions = {
  title: 'Log In'
};

const mapStateToProps = state => {
  let errors = [];
  if (state.auth.errors) {
    errors = Object.keys(state.auth.errors).map(field => {
      return { field, message: state.auth.errors[field] };
    });
  }
  return {
    errors,
    isAuthenticated: state.auth.isAuthenticated
  };
};

// const mapDispatchToProps = dispatch => {
//   return {
//     login: (phone, password) => {
//       return dispatch(auth.login(phone, password));
//     }
//   };
// };
const mapDispatchToProps = {
  login
};

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

1 个答案:

答案 0 :(得分:0)

所以我认为问题在于您没有使用任何Redux中间件,这些中间件都可以使您编写返回函数的动作创建器。

现在,如果您不使用redux中间件,则只能返回这样的操作

ERROR in ./src/app/menu/transaction/result/result.component.scss
(Emitted value instead of an instance of Error) CssSyntaxError: C:\TeamProjects\Web\Dev\Portal\node_modules\@swimlane\ngx-datatable\release\assets\icons.css:9:4: Can't resolve 'fonts/data-table.svg' in 'C:\Projects\Web\Dev\Portal\src\app\menu\transaction\result'

尝试Redux-thunk库。

    for (_, value) in json["assets"] {
        for item in value.arrayValue {
            let url = item["urlImage"].stringValue
            print(url)
        }
    }

现在,在您的applyMiddleware函数中,我认为您可以将redux-thunk中间件以及当前的中间件放入其中。

放置后,我认为它不再会引发错误。

让我知道怎么回事。