Giter Site home page Giter Site logo

whats-the-context's Introduction

The time I played with the React Context API: a story.

For context (hah), we have been planning updates to our curriculum at EDA, and as part of that we considered moving from managing client side global state with Redux to with the React Context API. I took it upon myself to try it out in best-practice, which is an app that will eventually serve as a standard for naming, structure and application shape for the EDA curriculum - and it's also a great playground ;).

It was quickly apparently that between a provider and a hook, an easy implementation of Context wouldn't be hard at all (though we've chosen to keep Redux for a number of reasons)... but this simply wasn't enough for me, and thus this fork was born.

I wanted to find a clean and scalable pattern to work with Context. Initially the intention was that we could use this pattern in the curriculum, though it quickly got a little out of hand given the size of the apps we build (and the fact that it's for curriculum, not production)...

I had been recently introduced to the Clean Architecture, and as any good junior developer does, I took this on as gospel and applied it everywhere with little questioning. Having never worked on a bigger codebase before though, it was a really fun exploration in wrapping external dependencies, and then injecting dependencies at every layer with factory functions.

I knew I wanted the components themselves to only receive data from props, so while there was a brief iteration with custom hooks, I ended up using higher order components. This made testing the components an significantly more pleasant experience, but the higher order components... less so. (I'm actually curious to try this again at some point, I think my understanding of testing philosophy in particular has developed a lot since then.)

And then came along my excitement about recursion. I ended up writing some helper functions; wrappedWith (makes wrapping a component in multiple higher order components a slightly more readable experience) and createCombinedProvider (creates one context provider to wrap the app in, regardless of the number of contexts you have, and reduces the noise in the React dev tools component tree to only one layer per context - I was quite pleased with this one!)

The main bugbear with Context is that when you consume a particular context, your component is going to re-render on every change to that context, whether your component actually cares about that change or not. In a lot of cases, you can diminish this problem by separating out your contexts (i.e. not having one huge object), but the following scenario does regularly occur:

Say my PendingContext uses state, so has a value of [pending, setPending]. From one component, I want to set the pending state, but the state itself is only needed elsewhere.

I have to consume the PendingContext, e.g. const [, setPending] = useContext(PendingContext) - even though I have only destructured the setPending function, my component rerenders on every change to pending. There is no way to decouple the context, to only watch for changes in parts (or none) of it.

I saw a few attempts at solving this problem floating around online, using memoisation (though this is only intended to be used for performance, not preventing renders) or with some kind of Proxy, but nothing seemed like a great solution, and there definitely wasn't a widely used pattern that I could find... so naturally I thought I'd try my hand at creating one.

Essentially, I ended up with a deep appreciation for Redux :)

I found one solution by using some extra abstraction, but I couldn't understand why it worked one way and not another, and didn't want to use the code until I understood it. I have another idea that I've yet to try, but the plotting continues!

Setup

To get this repo working on your computer, you'll need node installed. After cloning this repo:

cd whats-the-context
cp server/.env.example server/.env
npm install
npm run db:migrate
npm run db:seed
npm test
npm run dev

The server should be listening at http://localhost:3000. As you'll be able to tell, I have a real passion for design and CSS ;)

whats-the-context's People

Contributors

don-smith avatar lache-melvin avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.