redux-easy-connect

0.0.18 • Public • Published

#redux-easy-connect npm Codeship Status for kenanberbic/redux-easy-connect Known Vulnerabilities

Redux easy connect contains:

  • ReduxComponent - Base class that provide redux CONNECT action on easy way (ONLY REACT)
  • reduxExtend - Same like base class, but it's implemented using class prototype. (REACT AND REACT NATIVE)
  • TestHelper - Provide functions that allowing access to component directly. This include redux actions, state, reducers and public functions
  • setType - Init rule for all action types

How to use

import {reduxExtend,
        ReduxComponent,
        TestHelper,
        setType} from 'redux-easy-connect';

// Export component (ReactJS, ReactNative)
export default reduxExtend(Component);

// Export component (ReactJS)
class Example extend ReduxComponent
export default Example.CONNECT

// Include component
<Example
    actions={ExampleActions}
    reducers={{userStore:["user"]}}
    services={{AuthService}}
    />

// set action type
export const EXAMPLE_GET_USER = setType("example/GET_USER");

// use action type with dispatch
dispatch(EXAMPLE_GET_USER({/* props that will be provided to reducers */}))

// use action type in reducers
switch(type)
    case EXAMPLE_GET_USER.type :
         /* props that will be provided to component */
         break;

// Call actions
this.Actions.getUser(1);

// Call services
this.Services.AuthService.getUser(1)

// Reducers
this.props.user

// Use test helper
const component = TestHelper.getComponent(rendered, Example);
// rendered created by react-test-renderer

component.setState(/**/);
component.Actions.getUser(1);
await component.waitForAllState();
await component.waitForAllDispatch();

expect(component.props.user).toBeInstanceOf(Object);

// Use test helper for load external javascript library''s
const window = await TestHelper.loadScript(
                                            jsdom.JSDOM,
                                            'path to script',
                                            {jsdom options} ||
                                            DEFAULT_JSDOM_OPTIONS /* isn''t required */);

// Use mock''s with global fetch
it('should expose global fetch object', TestHelper.isFetchGlobal);
const output = await TestHelper.mock([{
                                        url:'http://localhost:3000/test',
                                        body:{output:"example"},
                                        status: 200}]);

// DEFAULT_JSDOM_OPTIONS
{
    resources: 'usable',
    runScripts: "dangerously",
    url: "http://localhost:8080",
    referrer: "http://localhost:8080",
    contentType: "text/html",
    userAgent: "Mellblomenator/9000"
}

Example

npm install
npm test
npm start
http://localhost:3000

reduxExtend / ReduxComponent

Props Type Include Example Description
actions prop actions={UserActions} this.Actions.getUser() Include list of actions that can be accessible in component
services prop services={{UserService}} this.UserService.getUser() Include list of services that can be accessible in component
reducers prop reducers={{userStore:["user"], authStore:true}} this.props.user, this.props. "all props from auth store" Include list of reducers and props that can be accessible in component
waitForAllDispatch func component. waitForAllDispatch() Continue to execute code after all actions finished with executing. ONLY FOR TESTS
waitForAllState func component. waitForAllState() Continue to execute code after all state actions finished with executing. ONLY FOR TESTS
onDispatchEnd event onDispatchEnd(args){ } *
onStateEnd event onStateEnd(args){ } *

TestHelper

| Func | Arguments | Example | Description | | --- | --- | --- | --- | --- | | getComponent | RenderedComponent, Class component name | TestHelper. getComponent(rendered, Example): return Example; | Find and return react component | | loadScript | JSDOM, javascript path, options | TestHelper.loadScript(JSDOM, 'script path') : return window | Loading external javascript libs like a google maps | | isFetchGlobal | | it('should expose global fetch object', TestHelper.isFetchGlobal); | Test you api calls with global fetch | | mock | [{url, body, status}] | TestHelper. mock([{ url: "http://localhost/test", body: {example:"test"}, status: 200}]) : return Promise | Mock http requests made using fetch |

Full example

Action types

import {setType} from 'redux-easy-connect';

export const EXAMPLE_GET_USER = setType('example/GET_USER');
export const EXAMPLE_SAVE_USER = setType("example/SAVE_USER");
export const EXAMPLE_DELETE_USER = setType("example/DELETE_USER");

Redux store - Include services directly in actions

function configureStore(initialState) {
    return createStore(rootReducer, initialState, compose(
        applyMiddleware(
            thunk.withExtraArgument(Services) // Include services like last params,
            routerMiddleware(history),
            reduxImmutableStateInvariant(),
        ),
        window.devToolsExtension ? window.devToolsExtension() : f => f));
}

const store = configureStore({});

export default store;

Action example

import {EXAMPLE_GET_USER, EXAMPLE_DELETE_USER, EXAMPLE_SAVE_USER} from '../actionTypes';

export default class ExampleActions {
    static getUser(id) {
        return async (dispatch, getState, {UserService}) => {
            const user = UserService.getUser(id);
            dispatch(EXAMPLE_GET_USER({user}));
        }
    }

    static saveUser(user) {
        return async (dispatch, getState, {UserService}) => {
            const output = UserService.saveUser(user);
            dispatch(EXAMPLE_SAVE_USER({user:output}));
        }
    }

    static deleteUser(user) {
        return async (dispatch, getState, {UserService}) => {
            const user = UserService.deleteUser(user);
            dispatch(EXAMPLE_DELETE_USER({user}));
        }
    }
}

Reducer example

import {EXAMPLE_GET_USER, EXAMPLE_DELETE_USER, EXAMPLE_SAVE_USER} from '../actionTypes';

const initialState = {
    user: null
};

export default function userReducer(state = initialState, action) {
    switch (action.type) {
        case EXAMPLE_GET_USER.type:
            return Object.assign({}, {user:action.user});
        case EXAMPLE_SAVE_USER.type:
            return Object.assign({}, {user:action.user});
        case EXAMPLE_DELETE_USER.type:
            return Object.assign({}, {user:action.user});
        default:
            return state;
    }
}

Component example

import React from 'react';
import {reduxExtend, ReduxComponent} from 'redux-easy-connect';

// export class Example extends ReduxComponent
export class Example extends React.Component{
    constructor(props){
        super(props);

        this.handleAddUser = this.handleAddUser.bind(this);
        this.handleGetUser = this.handleGetUser.bind(this);
        this.handleDeleteUser = this.handleDeleteUser.bind(this);
    }

    handleAddUser(){
        const user = {id:1,name:"Example",email:"example@example.com"};
        this.Actions.saveUser(user);
    }

    handleGetUser(){
        this.Actions.getUser(1);
    }

    handleDeleteUser(){
        this.Actions.deleteUser(1);
    }

    handleExampleService(){
        this.Services.AuthService.login(/* props */);
    }

    render(){
        return (
            <div>
                <button onClick={this.handleAddUser}>Add user</button>
                <button onClick={this.handleGetUser}>Get user</button>
                <button onClick={this.handleDeleteUser}>Delete user</button>
                <div>{this.props.user && JSON.stringify(this.props.user)}</div>
            </div>
        );
    }
}

export default reduxExtend(Example);
// export default Example.CONNECT;

Test example

import React from 'react';
import renderer from 'react-test-renderer';
import {TestHelper} from 'redux-easy-connect';
import store from '../store'

import ExampleActions from '../example/actions';
import CONNECT, {Example} from '../example';

it('renders example with action button add user', async () => {
    const rendered = renderer.create(
        <CONNECT
            store={store}
            actions={ExampleActions}
            reducers={{userStore:["user"]}}
        />
    );

    const component = TestHelper.getComponent(rendered.getInstance(), Example);
    component.handleAddUser();
    await component.waitForAllDispatch();

    const json = rendered.toJSON();
    const messageContainer = json.children[json.children.length - 1];
    expect(messageContainer).toBeInstanceOf(Object);
    expect(messageContainer.children).not.toBeNull();
    expect(messageContainer.children.length).toEqual(1);
    expect(messageContainer.children[0]).toEqual('{\"id\":1,\"name\":\"Example\",\"email\":\"example@example.com\",\"action\":\"SAVE\"}');
    expect(json).toBeTruthy();
});

Package Sidebar

Install

npm i redux-easy-connect

Weekly Downloads

26

Version

0.0.18

License

ISC

Last publish

Collaborators

  • kberbic