Redux не работает на React Native (Инвариантное Нарушение) - PullRequest
0 голосов
/ 11 ноября 2019

Сообщение об ошибке:

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

Это ошибка в коде или это связано с некоторым обновлением пакета?

Я получаю следующую ошибку: " Нарушение инварианта: недопустимый тип элемента: ожидается строка (для встроенных компонентов) или класс / функция (для составных компонентов), но получено: undefined. ВыСкорее всего, вы забыли экспортировать ваш компонент из файла, в котором он определен, или вы, возможно, перепутали импорт по умолчанию и имена."

1 Ответ

0 голосов
/ 11 ноября 2019

Тебе нужно будет немного отследить свой конец. Эта ошибка обычно возникает, когда вы пытаетесь отобразить компонент, который не существует (или не существует по указанному пути), что невозможно определить, не имея доступа к большей части проекта.

В AddScreen, TodoList и Header убедитесь, что все они export default. И если они рендерит какие-либо внешние компоненты, вам нужно будет проверить их на то же самое, если они импортированы одинаковым образом.

Один из способов отладки - удалить каждый компонент по одному и посмотреть, какой из них сломается. .

------- ОБНОВЛЕНИЕ ---------

Глядя на ваш проект на GitHub, я вижу, что два компонента называются export.

Измените 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
...