【问题标题】:Redux not working on React Native (Invariant Violation)Redux 无法在 React Native 上运行(不变违规)
【发布时间】:2019-11-12 22:17:11
【问题描述】:

错误信息:

https://imgur.com/LBNyl2M

App.js

import React, { Component } from 'react';
import { StyleSheet } from 'react-native';
import { Provider } from 'react-redux';
import Layout from './containers/Layout/Layout';

import store from './store/index';

export default function App() {

    return (

      <Provider store={store}><Layout/></Provider>

    );

}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
});

index.js

import { createStore } from 'redux';
import reducer from './reducer';

const store = createStore(reducer);

export default store;

reducer.js

import * as actionTypes from './actions';
import moment from 'moment';

const initialState = {

    itemList: [],
    idCount: 0,
    text: 'Write your to do item!',
    chosenDate: 'no-date',
    activeItems: 0,
    completedItems: 0,
    showCompletedList: false

}

const reducer = (state = initialState, action) => {

    switch(action.type){

        case actionTypes.ADDTOLIST:

            const objItem = { 'id': state.idCount+1, 'text': state.text, 'date': state.chosenDate, 'completed': false, 'displayTextInput': false, 'pickerVisible': false };
            return {
                ...state, 
                itemList: [...state.itemList, objItem],
                idCount: state.idCount+1,
                activeItems: state.activeItems+1
            }

        case actionTypes.REMOVEFROMLIST:

            let oldItemList = [...state.itemList];
            let index = oldItemList.indexOf(action.item);

            if( index !== -1) oldItemList.splice(index, 1);

            return {
                ...state,
                itemList: [...oldItemList],
                activeItems: action.item.completed ?  state.activeItems : state.activeItems-1,
                completedItems: action.item.completed ?  state.completedItems-1 : state.completedItems
            }

        case actionTypes.EDITITEMDATE:

            oldItemList = [...state.itemList];
            index = oldItemList.indexOf(action.item);

            if(index !== -1){
                oldItemList[index].date = state.chosenDate;
                return {
                    ...state,
                    itemList: [...oldItemList]
                }
            }

            return state;

        case actionTypes.EDITITEMSTATUS:

            oldItemList = [...state.itemList];
            index = oldItemList.indexOf(action.item);

            if(index !== -1){
                oldItemList[index].completed = !oldItemList[index].completed;
                return {
                    ...state,
                    itemList: [...oldItemList],
                    activeItems: action.item.completed ?  state.activeItems+1 : state.activeItems-1,
                    completedItems: action.item.completed ?  state.completedItems-1 : state.completedItems+1
                }
            }

            return state;

        case actionTypes.EDITITEMTEXT:

            oldItemList = [...state.itemList];
            index = oldItemList.indexOf(action.item);

            if(index !== -1){
                oldItemList[index] = state.text;
                return {
                    ...state,
                    itemList: [...oldItemList]
                }
            }

            return state;

        case actionTypes.TOGGLETEXTINPUT:

            oldItemList = [...oldItemList];
            index = oldItemList[index].indexOf(action.item);

            if(index !== -1){
                oldItemList[index],displayTextInput = !oldItemList[index],displayTextInput;
                return {
                    ...state,
                    itemList: [...oldItemList]
                }
            }

            return state;

        case actionTypes.FILTERACTIVEITEMS:
            return {
                ...state,
                showCompletedList: false
            }

        case actionTypes.FILTERCOMPLETEDITEMS:
            return {
                ...state,
                showCompletedList: true
            }

        case actionTypes.HANDLECHANGETEXT:
            return {
                ...state,
                text: action.text
            }

        case actionTypes.HIDEPICKERINITEM:

            oldItemList = [...state.itemList];
            index = oldItemList[index].indexOf(item);

            if(index !== -1){
                oldItemList[index].isVisible = false;
                return {
                    ...state,
                    itemList: [...oldItemList]
                }
            }

        case actionTypes.SHOWPICKERINITEM:

                oldItemList = [...state.itemList];
                index = oldItemList[index].indexOf(item);

                if(index !== -1){
                    oldItemList[index].isVisible = true;
                    return {
                        ...state,
                        itemList: [...oldItemList]
                    }
                }

                return state;

        case actionTypes.HANDLEPICKER:

            return{
                ...state,
                chosenDate: moment(action.datetime).format('MMM, Do YYYY HH:mm') 
            }

    }

}

export default reducer;

Layout.js

import React, { Component } from 'react';
import { Button, KeyboardAvoidingView } from 'react-native';
import AddScreen from '../../components/AddScreen/AddScreen';
import TodoList from '../../components/TodoList/TodoList';
import Header from '../../components/UI/Header/Header';

class Layout extends Component {

    state = {

        displayItems: false,
        pickerVisible: false

    }

    toggleItems = () => {
        this.setState({ displayItems: !this.state.displayItems });
    }

    showPicker = () => {
        this.setState({ pickerVisible: true });
    }

    hidePicker = () => {
        this.setState({ pickerVisible: false });
    }

    render () {

        let childComponent = <AddScreen 
                                toggleItems={this.props.toggleItems}
                                showPicker={this.props.showPicker}
                                hidePicker={this.props.hidePicker}
                                pickerVisible={this.props.pickerVisible}

                                />;

        if(this.props.displayItems){

            childComponent = <TodoList 
                                itemList={this.state.itemList} 
                                showCompletedList={this.state.showCompletedList}

                                />;

        }

        return (
           <KeyboardAvoidingView style={{flex:1}} behavior="padding">

                <Header />

                {childComponent}

                <Button title='Toggle Items' onPress={this.toggleItems} /> 

           </KeyboardAvoidingView>
        );
    }

}

export default Layout;

我在 github 上的完整项目: https://github.com/rvmelo/todolist-redux

这是代码中的错误还是与某些软件包更新有关?

我收到以下错误:“Invariant Violation: Element type is invalid: expected a string (for built-in components) or a class/function (for complex components) but got: undefined. 你可能忘了从定义组件的文件中导出组件,或者您可能混淆了默认导入和命名导入。"

【问题讨论】:

  • 你能提供你的reducer文件吗?
  • 是的,我已经这样做了
  • 错误说检查Layout的渲染方法。请发布您的Layout 组件。错误很可能存在。
  • 已经发布了我的 Layout.js 组件
  • 你能检查一下你在 Header 组件中是否有导出语句并且你正在返回 JSX 吗?

标签: reactjs native


【解决方案1】:

您将不得不做一些追踪。当您尝试渲染一个不存在的组件(或在您告诉它存在的路径上不存在)时,通常会出现该错误,如果没有访问大部分项目,这是不可能知道的。

AddScreenTodoListHeader 中确保它们都是export default。如果它们呈现任何外部组件,如果以相同方式导入,您将需要检查它们。

调试此问题的一种方法是一次删除每个组件,然后查看哪个组件会损坏。

-------更新---------

查看您在 GitHub 上的项目,我看到其中两个组件被命名为导出。

Layout 更改为以下内容:

import { AddScreen } from '../../components/AddScreen/AddScreen';
import { TodoList } from '../../components/TodoList/TodoList';

说明

当您执行export myFunction 时,它是一个命名 导出。所以你必须像这样使用命名的导入语法来导入它:

import { myFunction } from '..'

当您执行export default myFunction 时,它是一个默认 导出并且可以作为任何内容导入,因此您不要使用花括号,而是这样做:

import Anything from '...' //path to myFunction

【讨论】:

  • 我已经在 github 上上传了我的项目。链接在我的帖子里。要运行它,只需键入“yarn install”和“yarn start”
  • 好的,我明白了问题所在。我现在正在更新我的答案。
  • 我上面的解决方案的替代方法是删除你的容器consts 和只是export default connect(..,然后你可以保持导入相同。您的导出语句中多余的consts 是不必要的。
  • 在您建议的更改后,我不断收到相同的错误。你成功运行了我的项目吗?
  • 不,我没有时间。看起来Item 有同样的问题。您需要检查您的项目并确保它们都正确导入和导出。命名和默认都可以,只要确保根据它们的导出方式导入即可。
猜你喜欢
  • 2018-07-07
  • 1970-01-01
  • 2017-02-27
  • 1970-01-01
  • 2019-09-09
  • 2018-10-04
  • 1970-01-01
  • 2019-12-28
  • 1970-01-01
相关资源
最近更新 更多