@mattlanham @imjakechapman At Infinite Red, we used Redux for several years, and it worked fine. We used redux-saga for side effects and made a few helper libraries to make it better.

1/
@mattlanham @imjakechapman It wasn't quite working for us, so we started looking for something new.



2/
@mattlanham @imjakechapman One of our devs found MobX and MobX-State-Tree. MobX was a little too free-form for us, but MST fit the bill -- it had little boilerplate and also came with MobX-React which gave superior performance on state changes.

3/
@mattlanham @imjakechapman We tried it out on a couple projects and fell in love (this was about 2017). We've been using it on every project we can ever since, and as an agency we've had a chance to try it on a number of different types of startups and large scale apps.

4/
@mattlanham @imjakechapman I'll list some advantages over Redux, but keep in mind that Redux Toolkit came out recently which addresses several of these complaints, so if the cost of change to MST is too daunting, check that out.

5/
@mattlanham @imjakechapman Also, this is a topic with lots of feelings, so I'll caveat that this is just from our perspective, and YMMV. 😇



6/
@mattlanham @imjakechapman 1. Learning curve.

Redux is based on flux, and that comes with a shift in mentality with a lot of semi unintuitive concepts. There are lots of unfamiliar terms thrown around: dispatcher, reducers, action creators, thunks, sagas, epics, middleware.

This is a bit challenging.

7/
@mattlanham @imjakechapman One of my devs, Mark Rickert, put it this way:

"What really tripped me up when I started with Redux was… 'What?! I can’t just change the data?!'"

8/
@mattlanham @imjakechapman MST, on the other hand, within some constraints you're mostly working with functions and property assignment.

9/
@mattlanham @imjakechapman Example:

const User = types.model({
firstName: types.string
}).actions(user => ({
setFirstname(newName) {
user.firstName = newName
}
})

const myUser = User.create({ firstName: "Matt" })
myUser.setFirstName("Jamon")

9/
@mattlanham @imjakechapman You *do* have to use an "action" to change properties -- can't just do `myUser.firstName = "Jamon"`.

That's because within those actions, changes are "observed". And when an observer component uses myUser.firstName, it'll listen for changes, and re-render.

10/
@mattlanham @imjakechapman 2. Boilerplate

What you saw above was essentially a full MST implementation. To add a property that can be changed, you can change one file. With Redux you're often changing multiple files.

As your project complexity grows, it just scales how you'd expect.

11/
@mattlanham @imjakechapman 3. Side effects

In Redux, there isn't an official way to handle side effects (in Redux-Toolkit there is, btw). So you end up using thunks or sagas and epics to manage it.

In MST, there are async actions built-in as well as an advanced type of async action called a "flow".

12/
@mattlanham @imjakechapman Async actions are about as powerful as thunks, and flow is about as powerful as sagas.

...
.actions(user => ({
fetchGithub: flow(function* {
const data = yield api.fetchGithub(user.handle)
user.setGithub(data)
// more yields
})
})

13/
@mattlanham @imjakechapman 4. Everyone does Redux differently

There's not really one way to do Redux, and everyone does it differently (sometimes very differently). Conversely, we haven't really fundamentally changed how we write MST in 4 years. I think this speaks to the benefits of MST by itself.

14/
@mattlanham @imjakechapman 5. Performance

While it’s certainly possible to write performant Redux applications (we did for a couple of years), it’s not very hard to write sluggish ones.

15/
@mattlanham @imjakechapman React Redux is very well-written piece of software, but bloated middleware, unnecessary renders, un-memoized selectors, denormalized data structures, and more are all gotchas that can bite you. You can fix these with a bit of work, but you do have to be intentional about it.

16/
@mattlanham @imjakechapman MST, for the most part, in combination with MobX-React (or MobX-React-Lite which we use because we don't need class component support), makes it pretty idiomatic to write performant apps.

17/
@mattlanham @imjakechapman (Aside: we did run into a problem when having thousands of components on a web page recently. I didn't spend much time with the dev debugging it as he found a workaround, but the core team has it on our radar to figure out why. Shouldn't happen.)

18/
@mattlanham @imjakechapman 6. Runtime type checking

In MST, your properties are defined as runtime types:

const User = types.model({
firstName: types.string,
age: types.number
})

If the wrong type is fed into the model, you'll get a runtime error.

19/
@mattlanham @imjakechapman Not only that, but the TypeScript types are inferred from your runtime types, so you don't have to define the interface twice!

In this example, see how I never defined any TypeScript types? Yet TS can auto-complete the `country` property.

20/ Image
@mattlanham @imjakechapman With all of this said, there are tradeoffs. Redux has many times the community that MST does. It has many community libraries. Nearly all of the objections can be worked around or are addressed in Redux Toolkit. It's still the go-to state management library for many.

21/
@mattlanham @imjakechapman Documentation improvements are ongoing. We have excellent support from @EmilTholin and others on our Spectrum chat (often same-day responses. I recruited an all-new core team that is meeting monthly to go over PRs and issues. Big plans are in the works, as time allows.

22/
@mattlanham @imjakechapman @EmilTholin Wow this is long. I warned you! 😂

... if you'd like an expanded version, here's a blog post I wrote about it:

shift.infinite.red/why-infinite-r…
@mattlanham @imjakechapman @EmilTholin Questions? Happy to answer! Thanks for reading this far. ;-)
@mattlanham @imjakechapman @EmilTholin Great question @dev__adi.

For broader operations we often use a root store or substore action to coordinate across the tree.

A common example is `rootStore.reset()`. It then calls substores with `.reset()` which then manage their own resets.

Image
@mattlanham @imjakechapman @EmilTholin @dev__adi You can trigger flows from your own actions if you prefer, or you can listen using `onPatch` or other helper hooks.

Simplified example in next tweet....

@mattlanham @imjakechapman @EmilTholin @dev__adi // Example of triggering it manuallly
// ...
.actions(user => ({
async login(user, password) {
const token = await api.login(user.password)
user.setToken(token)
user.sendWelcomeEmail()
},
sendWelcomeEmail: flow(function* { ... })
})
@mattlanham @imjakechapman @EmilTholin @dev__adi // Example of listening to patches
// ...
onPatch(user, ({ op, path, value }) => {
if (op === "replace" && path === "/token" && value.length >= 0) {
// logged in
user.sendWelcomeEmail()
}
})

(Sidenote: this is where pattern matching would be nice....)
@mattlanham @imjakechapman @EmilTholin @dev__adi Here's an example from a real project -- we reach back to the rootStore from the loginStore in the `doLogout` action and reset everything. I like this imperative example best, because it's easy to figure out *why* the reset happened, rather than it being magic. Image

• • •

Missing some Tweet in this thread? You can try to force a refresh
 

Keep Current with Jamon 🚜

Jamon 🚜 Profile picture

Stay in touch and get notified when new unrolls are available from this author!

Read all threads

This Thread may be Removed Anytime!

PDF

Twitter may remove this content at anytime! Save it as PDF for later use!

Try unrolling a thread yourself!

how to unroll video
  1. Follow @ThreadReaderApp to mention us!

  2. From a Twitter thread mention us with a keyword "unroll"
@threadreaderapp unroll

Practice here first or read more on our help page!

More from @jamonholmgren

30 Nov 20
Life is ultimately calmer when one faces their problems head-on instead of avoiding them. You can avoid problems for quite a while, but in my 30s I had to face many of them. They eventually will catch up to you.
But don't do hard things alone.

Get a counselor, therapist, doctor, pastor, or life coach (depending on the situation). Or even just a close friend.* Have someone on your side.

(*Don't expect too much from friends. They're friends, not taking the place of trained pros.)
Build your conflict resolution skills! So many of my problems came about because I didn't know how to resolve conflicts effectively.

I see this in my friends. They suffer for weeks because they don't want to have one hard conversation. Or make commitments they can't keep.
Read 5 tweets
3 Mar 20
One of the things I’ve noticed about junior-level developers is they tend to optimize for the wrong things.

For example, they will get so nervous about taking too long that they won’t properly test their changes before submitting the PR.
This results in a lot more of the reviewer’s time to be spent testing and providing feedback. Which is fine here and there when you’re starting, but if it becomes a pattern, the reviewer can start to become impatient and lose trust.
Luckily, this isn’t too hard to fix.

Create a “PR checklist” that you use for each PR and check off the various things.

[ ] Works on Edge
[ ] Works in different screen sizes
[ ] Includes tests
[ ] Includes documentation

Ask your mentors to help you make this list.
Read 8 tweets
6 Jan 20
Last week, I got an email from a new consultancy founder asking some really good questions about running a consultancy. I answered her questions in detail in the email, but I'll also share some of the answers here.

1/
1. How do you manage the drought periods (those periods when no projects come in but you still have to keep the lights on)?

This is one of the toughest parts of having a development shop. Developers are _expensive_. Having them "on the bench" (as we say in this business) is

2/
...super difficult and can set you back months. Missing one week isn't just replaced by one week. If you have a 20% profit, that means every week missed is 4 weeks to make up the 80% cost, using each week's 20% profit.

3/
Read 15 tweets
8 Oct 19
I’m considering doing a free Twitter coding workshop, teaching people how to make a command-line app using a twitter thread.

Basically, i would sign up interested people by tagging them, and then step-by-step show them how to build the app. All in public.

Anyone interested?
Okay, to sign up, reply to this tweet with a terminal or command line screenshot with the results of “node -v” so I can see it’s installed.

To install Node: nodejs.org/en/download/pa…

Windows: Windows+R, “cmd.exe”
Linux: console (ctrl+alt+A)
macOS: Spotlight, “terminal”
Just needs to be Node 8+.
Read 33 tweets
3 Aug 19
So, anyone want to see my bigger backyard project that’s been in the works for a couple weeks?
So, last year we installed an above-ground 18’ pool.

I had my brother-in-law flatten out an area 25’ in diameter, though, because I figured if this experiment went well we might want to upgrade to a 24’ sometime later when the pool needed to be replaced.
(Bear with me...this will go kinda slow. I’m doing this between sets as I work out, and will probably be tweeting over the course of the evening. I promise lots of pictures though.)
Read 83 tweets
22 Jul 19
I received this Twitter DM from someone who asked the really interesting question: how do you manage underperforming team members?

I don't think we've entirely "solved" this, but after employing people for 10 years, I have thoughts.
1. Start from a position of empathy.

Most people _want_ to do better. They're struggling for various reasons, not all of which are professionally-related. Start by seeking to understand what might be impacting their ability to be productive.
Relationship problems, difficulty concentrating, lack of experience in a key area, communication problems, lack of sleep, slow computer, lack of enthusiasm, poor code by coworkers, lack of direction, too much direction -- all real reasons why people have underperformed for me.
Read 20 tweets

Did Thread Reader help you today?

Support us! We are indie developers!


This site is made by just two indie developers on a laptop doing marketing, support and development! Read more about the story.

Become a Premium Member ($3/month or $30/year) and get exclusive features!

Become Premium

Too expensive? Make a small donation by buying us coffee ($5) or help with server cost ($10)

Donate via Paypal Become our Patreon

Thank you for your support!

Follow Us on Twitter!