Technology

Eleni Chappen

When to Put Data in Redux

May. 17, 2018

Lots of internet ink has been spilled over when to keep data in an application state management system (like Redux) versus in a React component's internal state. While I've mentioned benefits to Redux on this blog before, it's important to understand the tradeoffs.

Keeping state in components has pros and cons:

Pro: your data is cleared when the component unmounts!

Con: your data is cleared when the component unmounts.

Likewise, keeping data in app state has pros and cons:

Pro: your data persists between components!

Con: your data persists between components.

Personally, I err on the side of keeping data out of app state. If I'm creating a new component and I'm unsure where to store my data, I'll use internal state, then port to Redux when it becomes necessary.

It's helpful to conceive of your app state as a collection of global variables. Normally, global variables are to be avoided. You wouldn't add global variables willy-nilly in a Rails or Python app. Have the same precaution when adding globals client-side.

Like any other global variable, when you make the decision to move your data into the global app state, it is now up to you to manage it. For instance, you'll probably need to clear your app state when a user logs out. When a user exits a multi-step form, you may need to clear any data that user entered.

Constructing your React container components thoughtfully can help you avoid manually managing state like this. With multi-step forms, I typically create a wrapper component that's responsible for rendering each step of the form, keeping all user-entered data in its own state. From this container, I can pass any of its state and functionality down to each step as props. It's a simple solution, but an often overlooked one, especially when Redux is already in your app and you see other components using it.

When an app uses Redux, it's impossible to prevent future maintainers from simply adding everything to app state. You can mitigate this by stressing in your documentation how keeping state in Redux can be dangerous. You can also practice predictable state patterns in your own components (like the form wrapper), setting good examples for future developers. But ultimately it's a hard thing to enforce, and this should be considered when deciding to add Redux to your application.

Eleni Chappen

What People Are Reading

Technology

1/6/17

React Lessons for Newcomers

At 20spokes, developers spend a roughly equal amount of time between Ruby on Rails and React. While we enjoy working in both frameworks, they are quite different in approach, and going from a Rails way of thinking to a React way of thinking can be an adjustment.

One major way in which these frameworks are different is that Rails takes care of a lot of architectural issues that React leaves open for interpretation. Coming from a Rails background, I found the openness of React to be a bit anxiety-inducing at first, but I've come to really embrace it, because it's forced me to think more carefully than ever about how other developers would approach my code.

As a team, we've also considered what our best practices should be towards React, as we all want to make our code understandable and friendly to anyone who encounters it. To that end, below is a (growing) list of our approaches to making our React projects not only maintainable, but enjoyable to work with.

Be relentless with components

The basic building block of React is the component. To those new to React, they can best be thought of as modules.

As a developer, I start to get nervous when I see large components that perform various functions. The solution to keeping your files short and sweet is to take every opportunity to break your objects into re-useable components. Having larger components may not seem like a big deal when starting a project from scratch, but if you relentlessly component-ize you'll thank yourself as your project grows.

There are some code smells to recognize when you should create new components. If you see lots of groups of markup within a single div, those groups should probably be their own component.

If we have lots of renderXXX functions within in one component that render more markup, that's usually a code-smell that whatever is being returned from those functions should be their own component.

Make components as reusable as possible by passing dynamic data as props.

Privilege functional components over class-based ones

In many cases, it's overkill to Use React's Component class for every component you create. Not all components need access to the Lifecycle Methods or local state that Component provides. Start with stateless functional components and turn them into React Component instances as needed.

Take advantage of PropTypes

We started the practice of listing out PropTypes at the bottom of every component, so other developers can quickly reference what props are needed or optional. Oftentimes, we'd investigate what data we should expect in a component by looking up examples of that component elsewhere in the codebase. This easily can be avoided by using PropTypes, which provide a quick way to see what data is being passed, and of what type that data should be. Here's an example from our reusable Button component:

Button.propTypes = {  
  text: PropTypes.string.isRequired,
  onPress: PropTypes.func.isRequired,
  disabled: PropTypes.bool,
  icon: PropTypes.string,
}

We're pointing this out because, while Facebook already notes it as a best practice in their documentation, it's something that's easy to skip over or forget to do. But for something that's not hard to do at all, it provides a lot of value when developing and maintaining your app.

Use Lifecycle Methods with care

Despite being incredibly powerful, lifecycle methods (like ComponentDidUpdate) can cause a lot of headaches to those new to React. Be careful when updating state or props within these methods, as it may cause infinite looping.

For this reason, I prefer to place lifecycle methods at the very top of a component declaration, so I can see all of that logic together when debugging.

Check out part 2 of this series, Redux Lessons for Newcomers.

Operations

8/29/16

Watch us eat our own dog food

20spokes is trying a new diet, so to speak. If you’re unfamiliar with the phrase “eating your own dog food,” it’s a common expression in the software world referring to a developer’s practice of using their own products. It’s said to have originated from 1970s television advertisements for Alpo dog food, where the owner of the company would make a point of feeding Alpo to his own dogs. So in its broader interpretation, “practice what you preach” would be an appropriate alternative. Either way, if we can help others build great products, we want to show that we can build our own great products as well.

It’s something we’ve thought about for a while, and now we’re finally taking the steps to make it happen. Client work will still always be our primary focus, but we have the team, the experience, and the aspirations; why wouldn't we work on our own ideas too? Like our clients, though, we don't want to jump into these ventures haphazardly only to end up with a well built app that nobody else wants. So we're putting these ideas through the same process of discovery, validation, and planning that we would with anyone who came into our office. In a way, by becoming clients of our own process, we’re getting our first helping of dog food!

Over the last week or so, we’ve adopted the mindset of a founder with a vision, and taken one of our ideas through the first steps of conception. Working through this process as the “founder” has already given us some great new insight, and we're excited to share this journey with you. So stay tuned for the next several weeks as we document all the steps we take and lessons we learn along the way; we're going to find out just how good our dog food tastes.

Trying to get your own product idea to market? Contact us to learn more about our process and how we can help.