Redux: When to spend props and when to take props from the state?

1

As you will know in redux we have access to the global state in any component with connect .

But my question is:

  • What is the best practice to pass props (or up to depth level) to nested components and when to take properties directly from state with redux?
asked by Jose Paredes 30.12.2016 в 11:52
source

3 answers

3

The question has a bit of ambiguity, since you mention two different design aspects although they are related in a certain point, first of all you mention that until depth level you pass the props through the components and on the other hand you mention the how to handle the global state of the application with Redux / Flux.

The first has to do with the management of the data within a React component with respect to the state and the props (setting aside Redux / Flux since that is another aspect), in this first aspect there are two essential rules that you must always take into account in a React component (Vista).

  • The props can only be mutated from a top-level component, for a component its props (this.props) are immutable, that is, the component can not mutate its own properties, it can only do so an external component.
  • The state is only accessible within the component itself, that is, unlike properties, the state is not accessible by external components, unlike the props, the state is mutable and can only be mutated within the component.

Based on these two considerations, we can only address the composition issue, remember that React uses composition instead of inheritance to create the interfaces.

You always use the props when you want to communicate changes to lower components in the hierarchy and the state you use internally in the component to manage its state.

In composition a common and highly recommended practice is to define components dumb (Dumb Components), these components have no state, only only reside in their props for which they are 100% dependent on the superior component, that makes them silly components.

Before moving on to examples with code, let's talk about the second aspect - > the global state of the application.

Both Flux and Redux offer the same architecture Event Driven, a circular architecture that imposes a communication scheme always unidirectional between the view, store and actions.

Here the interaction that interests you for your concern is the interaction of the View (React) with the Store, the Store communicates with the view in the case of Flux through callbacks and in the case of Redux through events this difference in communication is irrelevant, the essential thing is that the Store serves as a Global repository of the state of your application, how do you manage this global state to represent it in the individual components in the vita? is linking the state of the individual component with the state of the global Store.

Then from here I propose this rule to use the Global state of the application to mutate the state of individual components and the props you use for communication between components.

As in this example (ES6 / Flux)

export default class LoginComponent extends React.Component {
    render() {
        return(
            <div>
                {this.props.sesion ? this.props.sesion.nombreusuario : 'Debes iniciar sesion!'}
            </div>
        )
    }
}

export default class MenubarComponent extends React.Component {
    componentWillMount(){
        SesionStore.addSesionChangeListener(this._onSesionChange);
    }

    render() {
        return(
            <div>
                <div>item 1</div>
                <div>item 2</div>
                <LoginComponent sesion={this.state.sesion}/>
            </div>
        )
    }

    _onSesionChange = () => {
        let sesion = SesionStore.getSesion();

        this.setState(update(
            this.state,
            {
                sesion: {$set: sesion}
            }
        ))
    }
}

In this example the session must naturally be global in the application therefore it is stored in the Store, the fool component is LoginComponent and the main component is MenubarComponent. LoginComponent must show the logged in user but being a silly component can only reside in his props to show the logged in user therefore it must be the superior component who communicates the session change when the user logee, in your design you should always try to reduce as much as possible the sources of truth, in this case the source of the truth in the view is the state of the superior component MenubarComponent. MenubarComponent is not a silly component and is the one that links directly with the store to change its status when the SesionStore communicates a change in the session.

In this design silly components are always very concrete and reusable components, you should not add intelligent components inside them but you can continue nesting more foolish components at lower levels of a silly component's hierarchy.

Now what happens if a component in the view wants to communicate a change to a component that is several lower levels in the hierarchy? an alternative that exists is to use the context , but even Facebook warns you that it is not advisable to do this, with a good design and re-use of components you will not need to use the context for communications of this style.

    
answered by 30.12.2016 в 17:39
1

I would recommend starting from the difference drawn by Dan Abramov between visual components and container components .

Based on this distinction and according to Redux:

  • All the transformation logic of the state would be centralized in the reducers
  • The entry point of a certain view of the application should be a Container (sometimes these Containers are nested in other components, for example within a Route when using ReacRouter )
  • The container component would be responsible for passing parts of the state and functions invoking creators of actions in the form of props towards the visual components
  • The visual components would preferably be Stateless Functional Components and would be responsible for a single responsibility, to render those props and invoke the handlers when necessary (click, timer, etc)
  • Other visual components would be nested receiving some of the props of the parent component
  • When the amount of props you need to pass to the nested components becomes problematic, use a Container by nesting it in the right place and capture only the parts of the global state and the creators of actions that you need to pass as props .
  • Use local state components (based on classes) when you need to access the lifecycle methods (for example to load data via AJAX using componentDidMount )
  • Use components with state local when you need to store in that state data that supports the operation of the visual Component (for example to store open or closed status of an accordion component , something that we are probably not interested in having in the global state), not for other logics that should be at a higher level such as the container, the creators of actions or the reduction.
answered by 20.02.2017 в 03:54
0

Here I pass a thread with a good decision on the matter: link

    
answered by 01.01.2017 в 03:14