React Native Error:操作必须是普通对象,使用自定义中间件进行Aync操作

时间:2017-11-24 22:24:20

标签: react-native redux redux-thunk

我在登录过程中第一次应用redux-thunk。我收到以下错误(红色屏幕):

enter image description here

这是我的代码回购: https://github.com/samrao2/manager-4

以下代码段:

LoginForm.js:

我的代码仓库在这里:https://github.com/samrao2/manager-4

代码片段:

Actions / index.js:

import firebase from 'firebase';
import { EMAIL_CHANGED,
         PASSWORD_CHANGED,
         LOGIN_USER_SUCCESS
 } from './types';
//whenever the const variable below (action creator) is called
//it will be called with some amount of text and it returns an action, the text
//which is entered as an argument becomes the payload below
export const emailChanged = (text) => {
  return {
    type: EMAIL_CHANGED,
    payload: text
  };
};
export const passwordChanged = (text) => {
  return {
    type: PASSWORD_CHANGED,
    payload: text
  };
};
export const loginUser = ({ email, password }) => {
  //since we are using redux thunk/ async, the action creator now returns a function
  //instead of an object. Redux Thunk will see that this is a function and run it
  //the "then" will dispatch once the function is finisehd running
  return (dispatch) => {
  firebase.auth().signInWithEmailAndPassword(email, password)
    .then(user => {
      dispatch({ type: LOGIN_USER_SUCCESS, payload: user });
  });
};
};

loginform.js:

//we need this component to use react components library
import React, { Component } from 'react';
//this connect helper that will connect the action to the login form
import { connect } from 'react-redux';
//this is an action creator that we need to import in to connect with the reducers
import { emailChanged, passwordChanged, loginUser } from '../actions';
//these are our pre-styled components
import { Card, CardSection, Input, Button } from './common';

//login form is declared as an instance of the class "component"
class Loginform extends Component {
// this is the event handler as a method whose argument is text
  onEmailChange(text) {
//we have access to this prop from the action creator that is connected via the connect helper
    this.props.emailChanged(text);
  }
  onPasswordChange(text) {
    this.props.passwordChanged(text);
  }

  onButtonPress() {
const { email, password } = this.props;
this.props.loginUser({ email, password });  
  }
  render() {
    return (

    <Card>
      <CardSection>
        <Input
          label="Email"
          placeholder="email@gmail.com"
          onChangeText={this.onEmailChange.bind(this)}
//this comes from mapStateToProps and WE tell the component what its value is
//via the action creator and the reducer
          value={this.props.email}
        />
      </CardSection>

      <CardSection>
        <Input
          secureTextEntry
          label="Password"
          placeholder="password"
          onChangeText={this.onPasswordChange.bind(this)}
          value={this.props.password}
        />
      </CardSection>

      <CardSection>
        <Button onPress={this.onButtonPress.bind(this)}>
          Login
        </Button>
      </CardSection>
    </Card>
  );
  }
}
//this function is from the react-redux library and helps to map some piece of state
//onto the component
const mapStateToProps = state => {
  return {
//the global state object contains another object called auth, which containts the email
//property
    email: state.auth.email,
    password: state.auth.password
  };
};

//we are connecting/binding our action creator via the connect helper
//mapStateToProps is the first argument in the connect function
export default connect(mapStateToProps, {
  emailChanged, passwordChanged, loginUser
})(Loginform);

REDUCER:

//this is importing the email changed variable instead of the string in the action
import { EMAIL_CHANGED,
         PASSWORD_CHANGED
 } from '../actions/types';

//we need to do this otherwise the initial value will be undefined and the
//action will not work
const INITIAL_STATE = {
  email: '',
  password: ''
};

//this is the reducer below, its got 2 arguments, the state and action
export default (state = INITIAL_STATE, action) => {
  console.log(action);
//this switch statement switches over the action type, and depending on type
//the action decides what to do with it
  switch (action.type) {
    case EMAIL_CHANGED:
    console.log('action!');
//make a new object, take all the properties of my current object and include in
//that new object and take the email action.payload and include/overwrite that
//in the new object created
      return { ...state, email: action.payload };
    case PASSWORD_CHANGED:
      return { ...state, password: action.payload };
  //if none of the cases come out to be true above, it will default to the
  //beginning state with no changes
    default:
      return state;
  }
};

App.js:

import React, { Component } from 'react';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import firebase from 'firebase';
//reduxthnunk is helping us with aync operations, its a middlware
//to help with this middleware we need a ahelper from Redux library
//
import ReduxThunk from 'redux-thunk';
import reducers from './reducers';
import LoginForm from './components/LoginForm';


class App extends Component {
  componentWillMount() {
    const config = {
    apiKey: 'AIzaSyCCEY-CD1iSpSowupPZJcSuHEQ_yLvVzhg',
    authDomain: 'manager-2714d.firebaseapp.com',
    databaseURL: 'https://manager-2714d.firebaseio.com',
    projectId: 'manager-2714d',
    storageBucket: 'manager-2714d.appspot.com',
    messagingSenderId: '191493388327'
  };
  firebase.initializeApp(config);
  }
  render() {
    const store = createStore(reducers, {}, applyMiddleware(ReduxThunk));
    return (
          <Provider store={store}>
          <LoginForm />
        </Provider>
    );
  }
}

export default App;

1 个答案:

答案 0 :(得分:1)

这里的问题是文件app.js未正确保存,因为github repo中的以下代码证明该文件不包含使该代码有效的thunk元素:

  render() {
    return (
          <Provider store={createStore(reducers)}>
          <LoginForm />
        </Provider>
      );
    }
}

export default App;

同一文件中的代码是:

  render() {
    const store = createStore(reducers, {}, applyMiddleware(ReduxThunk));
    return (
          <Provider store={store}>
          <LoginForm />
        </Provider>
    );
  }
}

export default App;

正确保存文件解决了问题。