神刀安全网

Redux structure – a way to success

Today, I want to tell you  how my point of view on components and app structure has changed since I’ve been writing on React with Redux..

Redux structure – a way to success

What is all this bustle about?

There is so much hype about React and especially Redux, which has won the fight in flux stack already behind the scenes. Recently, Redux came into my life too, and, honestly, I like it very much. Of course, as any other tool, it has some advantages and disadvantages. It turns out that it’s just a tiny library with  good dataflow, and we don’t have  any framework over it, which tells  us how to implement features— only docs, articles and us. So we should do all the project structure  on our own…

Let’s figure it out

Everybody knows this, but let’s repeat it one more time: The Redux app has:

* Store – an object that keeps whole the state of our application

* Actions – plain objects representing the facts about “what happened” in our app

* Reducers – pure functions updating the state according to actions

All this staff responds to the side of logic.  Let’s look further… What’s about view? There are two types of components:

* Container – "smart" components,which are concerned with "how things work"

* Presentational -"dumb" components,which are concerned with "how things look"

The main idea here is that only a container component could manipulate the state. The presentation component just represents content according to props ,which are provided by the closest container and sometimes trigger a container’s callbacks.

Container component example:

import { connect } from 'react-redux' import { bindActionCreators } from 'redux' import { reduxForm } from 'redux-form'  import * as postsListActions from './actions' import PostsList from 'components/PostsList'  const mapStateToProps = (state) => {   return {     posts: state.postsListStore.posts   } }  const mapDispatchToProps = (dispatch) => {   const actions = bindActionCreators(postsListActions, dispatch);    return {     addPost: (postParams) => {       actions.addPost(postParams)     },   } }  const PostsListContainer = reduxForm({   form: 'AddPostForm',   fields: ['title', 'content'] }, mapStateToProps, mapDispatchToProps)(PostsList)  export default PostsListContainer 

Presentational component example:

import React from 'react'  import Item from './children/Item' import Form from './children/Form'  import './assets/style.scss'  class PostsList extends React.Component {    postBuilder(post, n) {     return (       <div className='post-list__item' key={n}>         <Item title={post.title} content={post.content}/>       </div>     )   }    render() {     return (       <div className='posts-list'>         <div className='posts-list__form'>           <Form {...this.props} />         </div>         <div className='posts-list__content'>           { this.props.posts.map(this.postBuilder) }         </div>       </div>     )   } }  export default PostsList 

Let’s do a little combination

After everything we’ve talked about, we can define two groups:

* (presentational components and their assets) – these can  be displayed according to received props and can trigger callbacks, which also come from props.

* (actions, reducers, containers) – these can  manage the application store and work with API. Know which props should be passed to inner presentational components.

So according to this,  we divide  this into two groups and get a structure like this:

components/  - PostsList/ modules/  - PostsList/  - reducers.js root/ store/ utils/ index.js

Let’s call the first group ‘components’ and the second  ‘modules’. We still have a file called ‘reducers’ where we combine reducers from each module.

Modules vs. Components

The main goal here is to understand  when you should create a module instead of using another component passing props and callbacks.  If you pass some props through a component just to get these props  inside the inner component or use a component in a module which is not fully responsible for this component behavior… Hmm, this might  be a good time to think about creating a new module.

Example of a module with its own actions, constants and reducers:

modules/   PostsList/    - actions.js    - constans.js    - reducers.js    - index.js

Example of a component with its own assets and inner components:

components/  PostsList/    assets/     - icon-plus.svg     - style.scss    Form/    Item/     - assets/     - index.jsx    index.jsx

If you know how to divide ‘smart’ and ‘dumb’ components in Redux, you can divide  modules too. The idea is the same. But let’s look at another  example that might not be  so simple.. First of all, remember that each module should be responsible for a  specific part. In the example above, we had one top-level presentational component with two children. They don’t know about store and their parent component tells  them everything they know about our application. But what would be changed if we had the ability to control, for example,  post-publication?  This picture illustrates what I mean:

Redux structure – a way to success

Now we have a component with its own logic because each item in a list could change its publication status. It isn’t a list’s problem at all. And it seems we should create a new module. Its structure can be a little confused because we only have  one index.jsx file and use other module actions. Using other module actions gives us the ability to change them. That is how our modules ‘communicate’ with each other – one module just changes  part of a store when another is listening.

Example of a module which uses another module’s actions:

import { connect } from 'react-redux' import { bindActionCreators } from 'redux'  import * as postsListActions from 'modules/PostsList/actions' import PostsListItem from 'components/PostsListItem'  const mapDispatchToProps = (dispatch) => {   const actions = bindActionCreators(postsListActions, dispatch);    return {     togglePostPublication: (id) => {       actions.togglePostPublication(id)     },   } }  const PostsListItemContainer = connect(null, mapDispatchToProps)(PostsListItem)  export default PostsListItemContainer 

The main advice here is that you shouldn’t be afraid of creating one more module. It doesn’t worsen  performance and doesn’t make the  code complex.

What’s in the end?

We received a collection of presentational components with their own styles and even images inside them, which are easy to test and reuse.  We  can even create a single collection of such components for multiple projects and plug in only the necessary components from project to project.  Also, we get a collection of logical cells – modules. And  it looks great to me because we can reuse them too. They are fully independent parts of logic. And the last benefit I see is that we can develop them separately from a project where they will be used. In this case, it’s much easier to concentrate on the result to find a better solution.

Well, we’ve got a cool UI constructor on our hands, thanks to Redux^^

转载本站任何文章请注明:转载至神刀安全网,谢谢神刀安全网 » Redux structure – a way to success

分享到:更多 ()

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址