connect redux函数无法与react-native

时间:2017-08-29 08:32:32

标签: reactjs react-native redux react-redux

我尝试使用react-native配置redux我遇到一个名为undefined的错误,当尝试从我的组件调用一个动作时,它不是一个函数, 似乎没有正确调用action()函数,我无法在表单组件中作为prop访问状态。
这是我的代码:

index.android.js

  import React, { Component } from 'react';
  import { Provider } from 'react-redux';
  import { createStore, applyMiddleware } from 'redux';
  // import ReduxThunk from 'redux-thunk';
  import reducers from './src/reducers';
  import { Form } from './src/components/Form';
  import { AppRegistry } from 'react-native';

  export class App extends Component {

    componentWillMount() {
      //here we will handle firebase sutup process for the authntication purpose . 
    }

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

  const styles = {
    main: {
      flex: 1,
      flexDirection: 'column',
      justifyContent: 'flex-start',
    }
  };

  AppRegistry.registerComponent('test', () => App);

Form.js

 import React, { Component } from "react";
 import { connect } from "react-redux";
 import { bindActionCreators } from "redux";
 import { Image } from "react-native";
 import { emailChanged } from "../actions";
 import {
Container,
ContainerSection,
Button,
Input
} from ".././components/common";

export class Form extends Component {
onEmailChange(text) {
    //call the action creator for the email
    this.props.emailChanged(text);
}

onPasswordChange(text) {
    //call the action creator for the password
}

onButtonPress() {
    //do something
}

renderButton() {
    return <Button onPress={this.onButtonPress.bind(this)}>Log in</Button>;
}

render() {
    return (
        <Container>
            <ContainerSection>
                <Image source={require("../../images/logo.png")} />
            </ContainerSection>
            <ContainerSection>
                {/* email input  */}
                <Input
                    label="Email"
                    placeholder="email@gmail.com"
                    value={this.props.email}
                    onChangeText={this.onEmailChange.bind(this)}
                    keyboardType="email-address"
                />
            </ContainerSection>
            <ContainerSection>
                {/* password input  */}
                <Input
                    label="password"
                    placeholder="password"
                    value={this.props.password}
                    onChangeText={this.onPasswordChange.bind(this)}
                    secure
                />
            </ContainerSection>
            <ContainerSection>{this.renderButton()}</ContainerSection>
        </Container>
    );
}
}

const mapStateToProps = state => {
return {
    email: state.auth.email,
    password: state.auth.password
};
};

function mapDispatchToProps(dispatch) {
return bindActionCreators({ emailChanged }, dispatch);
}

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

index.js(内部操作文件夹)

    import { EMAIL_CHANGED, PASSWORD_CHANGED } from './types';
    //it is an action creator 
    export const emailChanged = (text) => {
        return {
            type: EMAIL_CHANGED, 
            payload: text
        };
    };

    //it is an action creator 
    export const passwordChanged = (text) => {
        return {
            type: PASSWORD_CHANGED, 
            payload: text 
        };
    };

index.js(在reducers文件夹中)

import { combineReducers } from 'redux';
import AuthReducer from './AuthReducer';

export default combineReducers({
    auth: AuthReducer
    //   employeeForm: EmployeeFormReducer,
    //   employees: EmployeeReducer
});

AuthReducer.js

  import {
      EMAIL_CHANGED,
      PASSWORD_CHANGED
    } from '../actions/types';

  const INITIAL_STATE = {
      email: '',
      password: ''
    };

  export default (state = INITIAL_STATE, action) => {
      switch (action.type) {
        case EMAIL_CHANGED:
          return { ...state, email: action.payload };
        case PASSWORD_CHANGED:
          return { ...state, password: action.payload };
        default:
          return state;
      }
    };

This is the error returned

6 个答案:

答案 0 :(得分:4)

我也面临这个问题,并花费大量时间。.这个问题在该组件中无法正常工作。因为

export class Form  extents Component

因此不要执行

export default connect(
    mapStateToProps,
    emailChanged ,
)(Form);

解决方案:

删除导出关键字 例如:

 class Form  extents Component

并导入您必须使用的组件

的位置
 import Form  from './src/components/Form';

请勿使用

 import { Form } from './src/components/Form';

在这种情况下,请进行以下更改,

index.android.js

  import Form  from './src/components/Form';

Form.js

export class Form extends Component {
...
}
 export default connect(
        mapStateToProps,
        emailChanged ,
    )(Form);

希望这对您有帮助... 编码愉快!!

答案 1 :(得分:0)

尝试从任何组件使用调度调用。像这样

<强> Form.js

this.props.dispatch(emailChanged(text));

答案 2 :(得分:0)

尝试直接传递emailChanged。

返回bindActionCreators(emailChanged,dispatch);

答案 3 :(得分:0)

请在 Form.js

中尝试此操作
    import React, { Component, PropTypes } from 'react';
    import { connect } from 'react-redux';
    import { bindActionCreators } from 'redux';
    import { Image } from 'react-native';
    import { emailChanged } from '../actions';
    import { Container, ContainerSection, Button, Input } from '.././components/common';

    export class Form extends Component {
    constructor(props) {
        super(props)
        this.onPasswordChange= this.onPasswordChange.bind(this)
    }
        onEmailChange(text) {
            //call the action creator for the email 
            this.props.emailChanged(text);
        }

        onPasswordChange(text) {
            //call the action creator for the password
        }

        onButtonPress() {
            //do something
        }

        renderButton() {

            return (
                <Button onPress={this.onButtonPress.bind(this)}>
                    Log in
                </Button>
            );
        }

        render() {
            return (
                <Container>
                    <ContainerSection>
                        <Image source={require('../../images/logo.png')} />
                    </ContainerSection>
                    <ContainerSection>
                        {/* email input  */}
                        <Input
                            label="Email"
                            placeholder="email@gmail.com"
                            value={this.props.email}
                            onChangeText={this.onEmailChange.bind(this)}
                            keyboardType="email-address"
                        />
                    </ContainerSection>
                    <ContainerSection>
                        {/* password input  */}
                        <Input
                            label="password"
                            placeholder="password"
                            value={this.props.password}
                            onChangeText={this.onPasswordChange}
                            secure
                        />
                    </ContainerSection>
                    <ContainerSection>
                        {this.renderButton()}
                    </ContainerSection>
                </Container>
            );
        }
    }

    const mapStateToProps = state => {
        return {
            email: state.auth.email,
            password: state.auth.password
        };
    };

    FlipCardWithImage.propTypes = {
    emailChanged : PropTypes.func,

}
function mapDispatchToProps(dispatch) {
    return bindActionCreators({ emailChanged }, dispatch);
}

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

答案 4 :(得分:0)

最后我解决了错误,首先我改变了代码的结构,我将Provider和store存储在index.android.js直接,然后我更改了这个函数:

function mapDispatchToProps(dispatch) {
    return bindActionCreators({ emailChanged }, dispatch);
}

到此:

function mapDispatchToProps (dispatch) {
   return {
    emailChanged: () => dispatch(emailChanged())
   }
}

不使用bindActionCreators 然后我使用yarn add安装了依赖项,
感谢Sacha Best,您可能还需要确保通过npm安装以下软件包:

"babel-plugin-transform-decorators-legacy": "^1.3.4",
"babel-preset-es2015": "^6.24.1",
"babel-preset-react-native": "^3.0.2",
"babel-preset-stage-0": "^6.24.1",

还要确保你的.babelrc:

{
"presets": ["react-native", "es2015", "stage-0"],
"sourceMaps": true,
"plugins": [
["transform-decorators-legacy"],
]
}

要考虑的重要注意事项:由于各种原因,React和Redux团队通常都不鼓励使用connect()作为装饰器。规范仍然不稳定,Babel插件仍然在变化,即使插件工作,使用connect()作为装饰器也会导致开发人员的意外行为。

这对我有用,但如果它仍然无法使用,请尝试使用connect()作为函数而不是装饰器。

这些变化解决了错误!希望这会对你有所帮助。 谢谢你们。

答案 5 :(得分:0)

昨天发生了同样的事情。但是,当我将所有代码文件复制到以前的项目时,它起作用了。所以它必须是安装损坏的东西,因为安装已经使用相同的包以相同的方式完成。在一个项目中,连接起作用,而在另一个项目中,它不起作用。