Recommended Component Structure

File Structure

Below is the recommended way of originsing your component files.

MyComponent/
├── actions/
├── reducers/
├── sagas/
|── styles/
└-- index.js

The index.js is the entry point of your component (it's also the main file when we publish the component as a NPM module). We normaly define the React Component in index.js and it also includes all visual presentation in JSX in this file (unless it's a component that comes with very complicated presentation. In which case, you probably want to seperate your JSX code into different files). All other folders will contians:

  • actions folder : contains action type definitions & action creation functions
  • reducers folder: contains namespaced reducer functions. A reducer function will transite component state to next state depends on the actions received.
  • sagas folder: contains namespaced sagas. A saga is a generator function that yields redux-saga effects. You can consider redux-saga effects as command desciptions that to be executed at later time by redux-saga. Sagas are used for managing component action / event loop and managing effects (e.g. send network requests etc.)
  • styles folder: contains in-component styls / CSS that managed by lib JSS. You also can use traditional global CSS stylsheet to style your component. However, use the approach recommended here will make your component fully independent, plus you also get other benefits

ES6 Module Export

Your component entry point index.js should export the followings:

  • React Class / Function Component:
  • Exposed Action Types:
    • the types of actions may be sent out by this component
  • Exposed Action Creation Functions:
    • the action creation functions that are used to create actions that are accepted by this component.

Examples

React Function Component Example:

import { useComponentManager, AppContainer } from "fractal-component";
import * as actionTypes from "./actions/types";
import * as actions from "./actions/index";

function Counter(props) {
    /**
     * `useComponentManager` hook return value can be used
     * for either Object or Array destructuring assignment
     * i.e. you can either:
     * - `const [state, dispatch, getNamespaceData, componentManager] = useComponentManager(props, options)` OR
     * - `const { state, dispatch, getNamespaceData, componentManager } = useComponentManager(props, options)`
     */
    const [ state, dispatch, getNamespaceData, componentManager ] = useComponentManager(props, {
        initState: {
            ... // --- set init state here
        },
        namespace: "io.github.t83714/Counter",
        reducer: function(state, action) {
            ...
        },
        actionTypes,
        allowedIncomingMulticastActionTypes: [actionTypes.INCREASE_COUNT]
    });

    return (
        // ... Any actual render code here:
        // <div>
        //     <div>Counter</div>
        //     <div>
        //         <span>{state.count}</span>
        //     </div>
        // </div>
    );
}

Counter.propTypes = {
    appContainer: PropTypes.instanceOf(AppContainer)
};

export default Counter;

export { actionTypes, actions };

// --- export `Main React Component`
export default Counter;

// --- export `Exposed Action Types` & `Exposed Action Creation Functions`
export { actionTypes, actions };

React Class Component Example:

import {
    ComponentManager,
    AppContainerContext,
    AppContainer
} from "fractal-component";
import * as actionTypes from "./actions/types";
import * as actions from "./actions/index";

class Counter extends React.Component {
    constructor(props) {
        super(props);
        this.state = { ... }; // --- set init state here
        this.componentManager = new ComponentManager(this, {
            namespace: "io.github.t83714/Counter",
            reducer: function(state, action) {
                ...
            },
            actionTypes,
            allowedIncomingMulticastActionTypes: [actionTypes.INCREASE_COUNT]
        });
    }

    render() {
        ...
    }
}

/**
 * Besides passing `AppContainer` through React Context, 
 * you can also allow people to pass `AppContainer` through Component Props
*/
Counter.propTypes = {
    appContainer: PropTypes.instanceOf(AppContainer)
};

// --- Define contentType allow `AppContainer` pass through React Context
Counter.contextType = AppContainerContext;

// --- export `Main React Component`
export default Counter;

// --- export `Exposed Action Types` & `Exposed Action Creation Functions`
export { actionTypes, actions };

results matching ""

    No results matching ""