zalmoxisus / remote-redux-devtools

Redux DevTools remotely.
http://zalmoxisus.github.io/monitoring/
MIT License
1.8k stars 138 forks source link

Error: Actions must be plain objects. #73

Closed hussainb closed 7 years ago

hussainb commented 7 years ago

I am trying to include remote-redux-devtools in a react-native app, but I am consistently getting the below error in the app: Actions must be plain objects. Use custom middleware for async actions.

screenshot_1490714483

This error does not occur when not using composeWithDevTools

Below are the concerned files:

index.android.js

import React, { Component } from 'react'
import { AppRegistry, View } from 'react-native'
import { createStore, applyMiddleware } from 'redux'
import thunk from 'redux-thunk'
import { Provider } from 'react-redux'
import composeWithDevTools from 'remote-redux-devtools'

// Import the reducer and create a store
import { reducer } from './app/reducers/postsRedux'

// Add the thunk middleware to our store
const store = createStore(reducer, composeWithDevTools(applyMiddleware(thunk)))

// Import the App container component
import App from './app/App'

// Pass the store into the Provider
const AppWithStore = () => (
    <Provider store={store}>
        <App />
    </Provider>
)
AppRegistry.registerComponent('SocializeApp', () => AppWithStore)

App.js

import React, { Component } from 'react'
import { View, Text, ActivityIndicator, ScrollView, TouchableOpacity, StyleSheet } from 'react-native'
import { connect } from 'react-redux'

import { actionCreators } from './reducers/postsRedux'

const mapStateToProps = (state) => ({
    loading: state.loading,
    error: state.error,
    posts: state.posts,
})

class App extends Component {

    componentWillMount() {
        const { dispatch } = this.props

        dispatch(actionCreators.fetchPosts())
    }

    renderPost = ({ id, title, body }, i) => {
        return (
            <View
                key={id}
                style={styles.post}
            >
                <View style={styles.postNumber}>
                    <Text>{i + 1}</Text>
                </View>
                <View style={styles.postContent}>
                    <Text>
                        {title}
                    </Text>
                    <Text style={styles.postBody}>
                        {body}
                    </Text>
                </View>
            </View>
        )
    }

    render() {
        const { posts, loading, error } = this.props

        if (loading) {
            return (
                <View style={styles.center}>
                    <ActivityIndicator animating={true} />
                </View>
            )
        }

        if (error) {
            return (
                <View style={styles.center}>
                    <Text>
                        Failed to load posts!
          </Text>
                </View>
            )
        }

        return (
            <View style={styles.container}>
                <ScrollView style={styles.container}>
                    {posts.map(this.renderPost)}
                </ScrollView>

            </View>
        )
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
    },
    post: {
        flexDirection: 'row',
    },
    postNumber: {
        width: 50,
        justifyContent: 'center',
        alignItems: 'center',
    },
    postContent: {
        flex: 1,
        borderBottomWidth: 1,
        borderBottomColor: '#EEE',
        paddingVertical: 25,
        paddingRight: 15,
    },
    postBody: {
        marginTop: 10,
        fontSize: 12,
        color: 'lightgray',
    },
    center: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
    },
    button: {
        height: 50,
        justifyContent: 'center',
        alignItems: 'center',
        borderTopWidth: 1,
        borderTopColor: 'lightgray',
    }
})

export default connect(mapStateToProps)(App)

postsRedux.js

let results =
    [
        {
            "userId": 1,
            "id": 1,
            "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
            "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
        },
        {
            "userId": 2,
            "id": 2,
            "title": "qui est esse",
            "body": "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla"
        }
    ]

export const types = {
    FETCH_POSTS_REQUEST: 'FETCH_POSTS_REQUEST',
    FETCH_POSTS_RESPONSE: 'FETCH_POSTS_RESPONSE',
    CLEAR_POSTS: 'CLEAR_POSTS',
}

export const actionCreators = {
    fetchPosts: () => async (dispatch, getState) => {
        dispatch({ type: types.FETCH_POSTS_REQUEST })

        setTimeout(function () {
            dispatch({ type: types.FETCH_POSTS_RESPONSE, payload: results })
        }, 3000);        
    }
}

const initialState = {
    loading: true,
    error: false,
    posts: [],
}

export const reducer = (state = initialState, action) => {
    const { todos } = state
    const { type, payload, error } = action

    switch (type) {
        case types.FETCH_POSTS_REQUEST: {
            return { ...state, loading: true, error: false }
        }
        case types.FETCH_POSTS_RESPONSE: {
            if (error) {
                return { ...state, loading: false, error: true }
            }

            return { ...state, loading: false, posts: payload }
        }
    }

    return state
}
hussainb commented 7 years ago

Might be because of missing the curly braces { composeWithDevTools }, will confirm and close

zalmoxisus commented 7 years ago

@hussainb, yes, by default it is imported as store enhancer.