Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React Redux Responsibilities

I started learning react-redux-immutable couple of days ago and I am still quite confused about structuring my application. I have php (symfony/laravel MVC background) so it is not easy to get my head around some javascript concepts.

1) I have lines WrapperComponent:

export default function (props) {
    const style = {position: "relative"};
    const lines = props.lines;

    return (
        <div className='wrapper' style={style}>
            {lines.map(line => (
                <Line key={line.get("id")} {...line.toObject()} />
            ))}
            <Board />
        </div>
    );
}

2) That is connected to WrapperContainer

import Wrapper from '../components/WrapperComponent';

export default connect(
    function mapStateToProps(state) {
        return {
            lines: state.lines.map(line => {
                return line.set("board", {
                    width: state.board.get("width"),
                    height: state.board.get("height")
                });
            })
        };
    },
    function mapDispatchToProps(dispatch) {
        return {};
    }
)(Wrapper);

3) Then there is addLine action

export function addLine(type) {
    return {
        type: types.ADD_LINE,
        payload: {
            id: 3, top: 0, left: 0, diffX: 0, diffY: 0, type: type, board: {
                width: 0,
                height: 0
            }, active: false
        }
    };
}

4) That talks to LinesReducer

export default function LinesReducer(state = initialState, action) {
    switch (action.type) {
        case types.ADD_LINE:
            return state.push(
                Map(action.payload)
            );
        default:
            return state;
    }
}

5) So that WrapperContainer can listen to changes in state and re-render the lines

export default connect(
    function mapStateToProps(state) {
        return {
            lines: state.lines.map(line => {
                return line.set("board", {
                    width: state.board.get("width"),
                    height: state.board.get("height")
                });
            })
        };
    },
    function mapDispatchToProps(dispatch) {
        return {};
    }
)(Wrapper);

Now my question is:

Where do I put logic concerning the addLine action?

When I create a line I want to set its id AND I want to set its width same as width/height of another component.

I guess that actions should only transfer information from one place to another.

Then I am thinking ... maybe the logic should live at LinesReducer. But Lines reducer has no access to global state of the application so I don't know what width/height the new line should have.

Then there is WrapperContainer. Container has information about state of all application so it seems reasonable to loop through each line and set IDs if not set and update their width/height and other information.

But that doesn't seem right to me. I was thinking about one place that would gather information about global state of the application then it would add new line based on that information and nothing else would ever touch that line again. Except for another action.

Is this the right approach? I actually want to change the line width/height when another component's height/width changes so container makes the most sense to me.

EDIT:

Maybe:

1) set ID in action when the line is actually created (I just don't know how many lines there are already so I don't really know what ID should I set)

2) set width/height in container when it is passing lines to props (but if I eventually want to render the lines in another container I would have to duplicate the code there unless I create some "global" function that handles passing lines to component props in containers)

like image 502
Michal Avatar asked Jun 19 '16 22:06

Michal


1 Answers

You should keep your reducers as pure functions. It means that if you call them multiple times with the same arguments, they will have the same expected result, depending only on the arguments.

That said, the place you must put that type of logic is called action creator, which is actually your addLine function.

Action creators are exactly that—functions that create actions. It's easy to conflate the terms “action” and “action creator,” so do your best to use the proper term.

Action creators can also be asynchronous and have side-effects.

Learn more in the docs

Action creators can be aware of your current state by adding some middleware like redux-thunk:

Redux Thunk middleware allows you to write action creators that return a function instead of an action. The thunk can be used to delay the dispatch of an action, or to dispatch only if a certain condition is met. The inner function receives the store methods dispatch and getState as parameters.

like image 187
Diego Haz Avatar answered Oct 24 '22 17:10

Diego Haz