首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么我的"mapDispatchToProps“不能找到我的动作功能?

为什么我的"mapDispatchToProps“不能找到我的动作功能?
EN

Stack Overflow用户
提问于 2019-07-09 22:10:26
回答 1查看 259关注 0票数 1

我得到的具体错误与我所做的更改不同,然而,当前的错误是“操作可能没有未定义的类型.”。我对使用Redux非常陌生,但我一直在互联网上搜索任何足以让我遵循的内容。

TLDR:我所要做的只是向全局状态发送一个类似于以下内容的对象列表: records:{date: blah,.,var: blah},{.},这样我就可以在我整个应用程序的所有部分中使用它了。

我尝试过以各种方式更改mapDispatchToProps方法,但我仍然很难尝试将其连接起来。

我试着修改App.js,以及相应的操作、还原器和存储文件,但这一切似乎都与我所遵循的教程相同。如下所示:Ga2M

以下是所有相关守则:

App.js‘’

代码语言:javascript
运行
复制
import React, { Component } from 'react';

import {
createStackNavigator,
createAppContainer } from 'react-navigation';
import MainScreen from './screens/MainScreen';
import CostAnalysis from './screens/CostAnalysis';
import DriverLog from './screens/DriverLog';

// REDUX IMPORTS
import { createStore } from 'redux';
import { Provider } from 'react-redux';
import { recordReducer } from './reducers/recordReducer';

const MainNavigator = createStackNavigator({
  Home: {screen: MainScreen,
    navigationOptions: {
      header: null,
    }},
  CostAnalysis: {screen: CostAnalysis},
  DriverLog: {screen: DriverLog}
}, {
  defaultNavigationOptions: {
    header: null
  }
});

const AppContainer = createAppContainer(MainNavigator);

const store = createStore(recordReducer);

class App extends Component {
  render() {
    return (
      <Provider store={store}>
        <AppContainer />
      </Provider>
    );
  }
}

export default (App);

“”“

我在本例中导航到并发送数据的第二个屏幕

代码语言:javascript
运行
复制
import React, {Component} from 'react';
import {
  StyleSheet,
  View,
  Text,
  Dimensions,
  TouchableOpacity,
  YellowBox,
} from 'react-native';

// REDUX IMPORTS
import { connect } from 'react-redux';

import Icon from 'react-native-vector-icons/Ionicons';

const device = Dimensions.get('window');

class CostAnalysis extends Component {
    render() {
        return (
            <View style={styles.mainContainer}>
                <Text>Hey you got here!</Text>
                <Text>{this.props.records[0]}</Text>
            </View>
        )
    }
}

const styles = StyleSheet.create({
    mainContainer: {
        height: device.height - 60,
        position: 'absolute',
        bottom: 0
    }
});

function mapStateToProps(state) {
    return {
        records: state.records
    }
}

export default connect(mapStateToProps)(CostAnalysis);

“”“

MainScreen.js

“”“

代码语言:javascript
运行
复制
import React, {Component} from 'react';
import {
  StyleSheet,
  View,
  Text,
  Dimensions,
  TouchableOpacity,
  YellowBox,
} from 'react-native';

// REDUX IMPORTS
import { connect } from 'react-redux';
import ADD_RECORD from '../actions/types';
import {addRecord} from '../actions/index';

import Icon from 'react-native-vector-icons/Ionicons';

import LinearGradient from 'react-native-linear-gradient';
import SpecialInput from '../components/SpecialInput';
import DateTimePicker from 'react-native-modal-datetime-picker';
import SpecialText from '../components/SpecialText';
import GenericButton from '../components/GenericButton';

const devWidth = Dimensions.get('window').width;
const devHeight = Dimensions.get('window').height;

class MainScreen extends Component {

componentWillMount() {
  YellowBox.ignoreWarnings([
    'Warning: componentWillMount is deprecated',
    'Warning: componentWillReceiveProps is deprecated',
  ]);
}

// State stuff
state = {
  date: 'Date',
  dateColor: 'rgba(255,255,255,0.6)',
  starting: '',
  ending: '',
  gasPriceCurrent: '',
  visible: false,
}

stringifyNumbers = (inputObj) => {
    return inputObj.toString().replace(/[^0-9.]/g, '')
}

handleDateConfirm = value => {
  this.setState({
    date: value.toString().substring(4, 15),
    dateColor: 'rgba(255,255,255,1)'
  });

  // Hide the date picker
  this.hideDatePicker();
}

handleStartChange = (value) => {
  this.setState({
    starting: value
  });
}

handleEndChange = (value) => {
  this.setState({
    ending: value
  });
}

handleGasChange = (value) => {
  this.setState({
    gasPriceCurrent: value
  });
}

hideDatePicker = () => {
  this.setState({
    visible: false
  });
}

showDateTimePicker = () => {
  this.setState({ 
    visible: true,
    dateColor: 'rgba(255,255,255,0.6)'
  });
}

recordEntry = () => {

  const record = {
    date: this.state.date,
    startKM: this.state.starting,
    endKM: this.state.ending,
    curPrice: this.state.gasPriceCurrent
  }

// This is where I try to add the record to the list
  this.props.addRecord(record);

  // Now go to confirmation
  this.props.navigation.navigate('CostAnalysis');
  // Reset input fields after recording entry
  this.resetInput();
}

// Reset input fields
resetInput = () => {
  this.setState({
    date: 'Date',
    dateColor: 'rgba(255,255,255,0.6)',
    starting: '',
    ending: '',
    gasPriceCurrent: '',
    visible: false
  });
}

render() {
  return (
        <LinearGradient 
          colors = {['#051937', '#A8EB12']}
          style ={styles.homeScreen}
          locations = {[0.23, 1]}
          start={{x: 0, y: 0}}
          end={{x: 0, y: 1}}>
          <Text style={styles.heading}>Hello</Text>
          <Text style={styles.subHeading}>
            Please start recording your starting and ending gas amounts
          </Text>
          <View style={styles.inputContainer}>
          <TouchableOpacity onPress={this.showDateTimePicker}>
              <SpecialText
                  content = {this.state.date}
                  style={{
                    fontSize: 22,
                    color: this.state.dateColor
                  }}
              />
            </TouchableOpacity>
            <DateTimePicker
              isVisible={this.state.visible}
              onConfirm={this.handleDateConfirm}
              onCancel={this.hideDatePicker}
            />
            <SpecialInput
              placeholder = {"Starting"}
              iconName = 'ios-car'
              iconText= '  KM'
              maxLength={3}
              style={styles.inputStyle}
              value={this.state.starting}
              placeholderTextColor={'rgba(255,255,255, 0.6)'}
              onChange = {this.handleStartChange}
            />
            <SpecialInput
              placeholder = {"Ending"}
              iconName = 'ios-car'
              iconText= '  KM'
              maxLength={3}
              style={styles.inputStyle}
              value={this.state.ending}
              placeholderTextColor={'rgba(255,255,255, 0.6)'}
              onChange={this.handleEndChange}
            />

            <SpecialInput
              placeholder = {"Current Gas Prices"}
              iconName = 'ios-pricetags'
              iconText= '  cents'
              maxLength={5}
              style={styles.inputStyle}
              value={this.state.gasPriceCurrent}
              placeholderTextColor={'rgba(255,255,255, 0.6)'}
              onChange={this.handleGasChange}
            />

            {/* Record the entry into data storage */}
            <GenericButton 
              style={styles.recordButton}
              textColor={'#ffffff'}
              placeholder = "RECORD"
              onPress={this.recordEntry} />

            {/* RESET BUTTON */}
            <GenericButton 
              style={styles.clearButton}
              textColor={'#ffffff'}
              placeholder = "CLEAR"
              onPress={this.resetInput} />
          </View>
        </LinearGradient>
    );
  }
}

function mapStateToProps(state) {
    return {
        records: state.records
    }
}

// Here is where I noticed most of the errors pointing to
const mapDispatchToProps = dispatch => {
    return {
      addRecord: (record) => {
        dispatch(addRecord(record))
      }
    }
}

export default connect(mapStateToProps, mapDispatchToProps)(MainScreen)

“”“

我的recordReducer.js

“”“

代码语言:javascript
运行
复制
// recordReducer.js

import { ADD_RECORD } from '../actions/types'

const initialState = {
    records: ['Chicken Joe']
};

const recordReducer = (state = initialState, action) => {
    switch(action.type) {
        case ADD_RECORD:
            return {
                ...state,
                records: state.records.concat(action.value)
            };
        default:
            return state;
    }
}

export {recordReducer};

“”“

行动/index.js‘

代码语言:javascript
运行
复制
import ADD_RECORD from './types';

// Add Record Action
export const addRecord = record => {
    return {
        type: ADD_RECORD,
        payload: record
    }
}

“”“

行动/类型.

“”“

代码语言:javascript
运行
复制
export const ADD_RECORD = 'ADD_RECORD';

“”“

如前所述,我只想弄清楚如何在存储中保存数据,并在以后从任何组件/屏幕/视图中检索数据。

谢谢任何想帮助我的人!我已经连续干了12个小时了

编辑1:

这是我遇到的新错误。唯一的改变是,在actions/index.js中,我做了一个正确的named import

错误消息

EN

Stack Overflow用户

回答已采纳

发布于 2019-07-09 22:15:32

您在actions.js中有一个错误。你在进口:

import ADD_RECORD from './types';

但是,这是一个默认的导入,而types.js正在执行一个命名的导出

export const ADD_RECORD = 'ADD_RECORD';

您需要使用匹配的导入和导出语法,否则导入的值将是undefined。这导致操作对象有一个未定义的type字段,从而导致Redux错误。

因此,将actions.js改为使用指定的导入,正如您在还原器文件中所做的那样:

import {ADD_RECORD} from "./types";

此外,当您的atm代码工作时,可以简化mapDispatchMainScreen.js中的定义,以使用mapDispatch

const mapDispatch = {addRecord};

另外,我强烈建议您使用我们的新的Redux初学者工具包,它会自动为您生成操作类型和操作创建者函数,这样您就不必手工编写它们。

票数 2
EN
查看全部 1 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56961108

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档