Functional Programming in JavaScript and React (Part Two)

Adam Mackintosh
27 min readNov 9, 2018

NOTE: I did not mean to publish this. But I will leave it anyway yolo style. It’s still in progress. I wouldn’t recommend reading it, but you could.

PART TWO — THE IMPORTANT FACTORS

The way I would like you to approach these next parts is to imagine the type of things you should and must care about in order to be an extreme baller logic spewing machine. I will get you primed up now. State. Everything revolves around state. The millisecond your state gets mangled, you are toast.

State integrity is the most important thing in every app.

Imagine you had a calculator that forgot which number it was at or it accidentally returned the wrong number. It would pretty much be the absolute worst calculator ever made, unless it was TrollCalculator.exe. In that case, it could be among the best at what it was designed for.

Having issues with state is a little bit like yelling out random numbers while your friend is trying to count how many people he/she sees logged in — important, important, important.

Did you know: Redux is responsible for managing app-wide state in a React app and provides you with a formal state change-management process?

Key properties of an app:

  1. An app can be viewed as an Object, at a moment in time when observed
  2. An app probably requires state
  3. An app can respond to any event we specify
  4. An app can initiate or facilitate any action

Functional Reactive Programming isn’t something my grandma can absorb in 20 minutes while you talk to her at the grocery store, so don’t feel bad if you are confused at some times. It gets comfortable over time as you understand more patterns. Like Chess, you play Chess better once you memorize a few patterns and how they unfold over time.

Today, I would like to declare some patterns, and you can use them after.

But first, I occasionally like to give nods to other people for their incredible work in the community. Eric Elliott is one of those people, and this article here is a pre-requisite to this article. I believe it should be read three times to complete the 2D closed polygon of your understanding. Put this in your Bookmarks along with other logical gems you find:

Reactive Programming

Before we get to the meat of these styles, we must talk about functional programming and reactive programming.

It’s a matter of describing ancestors first so that children make sense. We need the context awareness.

Note: Adobe Photoshop has context awareness with its Healing Brush. This means you can drag the brush through an area, and Photoshop calculates optimal blending of adjacent pixels.

My goal is to install more context awareness into you, so you can write bulletproof apps perhaps more frequently.

Function as an Object (FaaO)

I just made up that acronym. It’s not important. When I say Object, I mean a thing or node that could be connected to another node. JavaScript happens to excel when it comes to objects that can efficiently double as functions.

Let’s conduct a little test, so we can see a Function that is also an Object. It is a testament to the incredible efficiency that is possible in JavaScript:

const executable = () => {
executable.hello = 'world'
return executable
}
// LOOK AT IT
console.log(executable)
// => { [Function] hello: 'world' }
// EXECUTE IT
console.log(executable())
// => { [Function] hello: 'world' }

Quick Mention: Check these out below — they are atomic building blocks of logic. You can build the most incredible things I’ve ever seen by simply composing these things together as if we were in some deformed Math class using ideas instead of numbers.

const function = () => {}const object = {}const array = []

Think of it this way, an Object can store some state. An Array can hold a collection of Objects, and a Function is a place to do work, but like in real life, there is a purpose to that work, and that’s why it’s flow best served one-way. You do the work until you get there, and then maybe you report back or keep going. Many programming rules apply here: encapsulation, sole responsibility, etc.

Encapsulation

?

Sole Responsibility

Note how I didn’t say single responsibility. This can be confusing for people. A function should be responsible for approximately one idea. An idea could consist of more than one thing. A Function called getUserData() sounds like it is only doing one thing. Introducing another ideas, may sprinkle a bit of chaos into the idea of getting user data. A function may also processUserData()which is still doing approximately one idea, but there is room to do more as long as it’s related to processing user data. Ignore any subpar naming conventions. Naming stuff is hard.

The same rules are true when you write essays in English class. Reading a paragraph that is talking about several things is confusing to readers. ‘What is the point?’ they might say. My point right now is that there is a balancing act inside functions. You have to gain intuition towards what is correct, and that may change depending on the circumstances (ie: project requirements, ie: context). No wonder this is so confusing for seasoned programmers. It’s a one word descriptor symbol for who knows what until you see the code.

Top 3 Symbols

Our above FaaO app is a pretty simple app. You can look at it or execute it, but there are two key takeaways: Objects have properties, meaning you can look at them and observe facts at the moment of observation. Objects can also have methods, meaning they can perform actions or respond to events. In JavaScript, you can go ahead and execute that Object.

Moving onward (continuous forward motion = good), three things pop into the forefront immediately:

  1. State
  2. Actions
  3. Events

If you drew those on paper as circles and connected them together, you would have a 2D triangle. Pretty cool? No probably not, but it is to me because I eat geometry for breakfast. A triangle is the strongest geometrical shape because it must be destroyed before it loses structural integrity. This makes people race to it in Physics and Mathematics. I love trianglios, the razor sharp cereal to start your day off right angle.

I love comedy as a tool to help describe. It’s the only way we are going to get through this material without lighting your hair on fire with the help of an accelerant.

Try to think in terms of Objects in JavaScript as traveling through water slides that are always tilted so gravity can help you. Imagine that in your head, some object bombing down the slide. Now, imagine someone violently ripped in there and grabbed the object. The scenery turns sour. This occurs inside your code as well and confuses people when they look at nice flowing Functions.

State

Apps generally require state management, but what is state:

  • memory
  • knowledge of current moment

Improperly or ineffectively managing state can turn into a nightmare with intensity that grows proportionately with the size and complexity of your app. I mention state early in this article because it’s the highest priority sub-system with which to maintain correctness. For example, if an app reports an incorrect user being logged in or an incorrect dollar amount, the quality of the app is immediately under review.

I would go as far as to say that state is the single most important aspect of every app.

State is the one thing that must be kept accurate and precise. Therefore, we need an official process that ensures state can maintain integrity. This is your first lesson about reactive programming. If changes to state are involved, there must be a strict process to handle propagation of changes.

Two great ways to simplify complex scenarios:

  1. Immutability
  2. One-way flow

Special Tips: You will be off to a great start if you try to always return something from your functions. Don’t modify things outside the function unless you need to; simply return them out of the function for the next point in time.

To understand those special tips, we need to discuss shared mutable state, and side effects.

Scary Stuff

One-way flow of information is great because it keeps interactions simple. One-way is simpler than two-way. This helps us reason about what the app is doing. It allows us to manage state in one direction. Things can be modeled with a start and a finish.

Start to finish, wait that sounds like executing a Function.

Remember when I said the proverbial water slide was tilted so that gravity can help you? Well, just as tilting a water slide too much could be a problem and make a grandma start crying even though she’s seen a lot of slides in her day, pushing data too quickly or pulling it in weird ways can cause problems. In JavaScript and also any programming language, things start to get scary when you introduce concurrency.

It’s really hard for me to write this Article because there are so many definitions that you will never see in a million years in beginner tutorials and YouTube videos. I feel a moral obligation to join them all together right now in 2018 for you and for me. I’m trying to talk about state, immutability, and asynchronous JavaScript, and all I can think is, “dang, they are going to explode if I tell them aboutdeterministic conconcurrency too early". I’m not taking the easy way out by neglecting to tell you about it.

Fig ?.? — Arrive alive

We are also going to talk about deterministic transformations, so put your seat belt on and grab your chosen style of liquid beverage — preferably coffee because caffeine is a central nervous system accelerant, and preferably also chew gum because it increases oxygen delivery to your brain via mastication which increases short term memory quantity and long term memory recall quality.

I need to emotionally release all this crap and find new keywords. This Article could be thought of as a compost heap that I just created. Some people will call it garbage, but they are missing the point. Imagine all the small interactions that are possible inside a compost heap. The compost heap could give life while it is composting, and it could help you later.

React JS isn’t called React for no reason. React was designed by solving the challenges and requirements of an asynchronous, data-centric app that has 2 billion users. Perhaps you’ve heard of Facebook? Imagine the sample size that design decisions could be compared against.

I underscore the importance of state in apps because events can happen at any moment. Asynchronous and parallel conditions bring significant risk to app state because data could be lost in transit. An app needs a correct action for every event that occurs. An app that responds incorrectly to an event can only cause confusion, either for the user or in the app state.

Actions

Apps can perform not only actions but also operations. Operations are the big brother of actions. For example, I could calculate that 1+1=2 but if I never tell anyone, there will be no action. When I talk about actions, I generally mean containers that are responsible for performing work — functions. An action usually has a start and finish. Functions also usually do.

If you want to perform an action, you probably want to execute a function.

Events

If actions are analogous to talking, events are analogous to listening. If you are listening, you may be recording changes to state as they occur. Therefore, events probably trigger state updates. Actions can trigger state updates as well, however.

Because an event can be observed, anything that can be observed has properties to observe. Therefore, most events should probably create, update, or return an Object, but only if the information might be cared about later. For example, when the mouse move event occurs, you may listen for the time when it passes through x,y: 1337, 1337. You may not wish to store any other co-ordinates unless you are a scientific researcher or something.

For example, here is a birthday party as an Object:

const birthdayParty = {
startTime: 5,
endTime: undefined,
}

Here is an action that inherits a huge problem due to lack of immutability during an asynchronous series of events:

const birthdayParty = {
startTime: 5,
endTime: undefined,
location: { ...address },
}
const driveToLocation = async (location) => {
return handleDriveCar(location)
}
driveToLocation(birthdayParty)
.then(badExperience => forEveryone(badExperience))
birthdayParty.location = { ...differentAddress }

Birthday party state was mutated after driving started. Let’s break it down forensically:

  1. Shared mutable state existed
  2. Asynchronous behavior existed
  3. A mutation action occurred in parallel with another action

Because the state was allowed to update during this driving action and it was not synchronous, the location changed before the action completed. If the driveToLocation() function is not aware of this state change, a) the change management process is subpar, and b) we see why shared mutable state is controlled by the devil — if conditions are asynchronous.

The solution could be to add the async keyword which will force the driveToLocation Promise-chain to complete before execution continues and updates the new location. Good? Not exactly. What if the birthdayParty.location mutation occurred in another file? Your async keyword plan would get destroyed immediately. This is why concurrency brings indeterminism.

The only way to fix such a nasty problem is to introduce some kind of messaging system. Here are three solution areas:

  1. Event emitters and observers
  2. Semaphores
  3. Callbacks (continuation-passing style)

All three of these solution areas involve your code picking up the proverbial phone and talking to another area of the app for purposes of coordination.

Notice how I keep talking about events happening, problems with state, and maintaining 100% accuracy and precision during state changes. Functional Reactive Programming is a very viable way to handle these type of situations. Through all this, there are two things that shine most important:

  1. State
  2. State changes

If state changes occur properly, state maintains integrity.

Dinosaurs beginning to respond poorly to change

Radical Quote: An app’s response to change is the most important factor towards maintaining state integrity.

This is where the reactive part of Functional Reactive Programming comes from. The program is reacting to changes and not screwing anything up, preferably in crazy asynchronous conditions. This makes perfect sense in the real world where wall feeds get updated while scrolling and where cancel buttons are pressed during actions and events. State is the crown jewel, and it must be protected like an infant human must be in the real world.

I did QA for years, so trust me when I say users basically navigate around your app ramming on the keyboard. It’s not you that we have to watch out for on the road while driving — it’s everyone else.

Just as learning can precede knowing, thinking about writing code in accordance to the best patterns we are currently aware of can precede writing code. Cancelling events or actions that are in mid-flight. If your paper airplane is flying at someone’s eyeball, you should have a way to stop it. The eyeball in our JavaScript case represents the cost of time, resource use, and UX quality.

Let’s setup some imagery. We are casually floating down a stream and perhaps some objects are being plucked out occasionally, or they fade out as needed. We don’t have to be floating, our stream could be pressurized and very deep underground where it is hard to see or change things.

Some things are for sure:

  • Traveling one way is good
  • Traveling downhill at the most efficient pace without pooping our pants is good

I have a bit of a Physics background, so some logic of Kinematics is useful here, such as perfectly elastic collisions. It’s not the math that is important though. It’s the system intuition you get from imagining Objects in a stream abruptly changing direction, and the turbulence that would arise from those events.

Remember, we are talking about events right now. Things happen. In Physics, every action has an equal and opposite reaction, and the Second Law of Thermodynamics exists. This means side effects are real. We might not know what they are until we see your project, you should always keep on the lookout for Externalities (in the Economics sense).

Streams

I don’t want to talk about streams too much, but they are important to mention during reactive programming conversations. What is a stream literally? Ignoring the velocity of flow, it is a channel that water is flowing through.

Do you know what else can flow through channels?

Data.

Channels are essentially how and where Objects can move from point A to point B. Data is very fluid-like. You don’t want your data to leak.

Analogous to channels are streams:

At the very minimum, data leaks cause:

  • Security concerns
  • Data loss
  • Bugs

I’ve never heard a concrete term for the concept of data leaks in apps. Bug is probably the parent descriptor word. Let’s just focus on the fact that leaking is a thing in the real world. Maybe it’s tolerable at the time, maybe it’s Maybelline, but definitely some stream is not fully optimized.

Notice in the definition above, that real streams and data streams are both continuous. If you like Calculus, you could study them. If you don’t like Calculus, we use it to send rockets to Mars and you should. This continuous nature is useful for actions and events that happen asynchronously.

A stream has a start and a finish. There is a finite distance, a positive direction, and a negative direction. The travel path is known. The app can be designed to respond to any events along the way. It can ignore events too, but there will certainly be a formal process that is followed when changes are made.

To wrap up this section, reactive programming is about reacting to changes properly by setting up the environment to handle changes and dodging problems with state. Data can be pushed or pulled; it can be pushed into somewhere or pulled in from somewhere. Data flow is typically one-way because events with respect to time are simpler. All of this will be handled immutably because a) integrity of state is of utmost importance and b) asynchronous and parallel operations are dangerous to state.

Let’s move on. Now that we have completed the action of streaming reactive data into your retinas, you can update your mental state to reflect these learning events.

If your entire app happens to be listening to the streams of state changes, actions, and events flowing through it, it can instantly re-coordinate anything you allow it to when a specific action or event happens. After that, you can start speaking in terms of pushing things or pulling them. You could push or pull towards or away from something.

Where & When

When doing asynchronous programming, the more simple and flat the list of steps, the less likely you are to encounter a problem. Your goal is to setup functions so that you don’t have to care about anything besides when and where to call them. They handle everything correctly based on what you supply them. If you examine React using this magnifying glass, you will see.

Does this sound familiar for other reasons? Imagine if someone posted on StackOverflow with a problem and you knew exactly where and when they were doing things incorrectly. You might help them solve it pretty quick. This is why your QA team members are obsessed with knowing what the steps were to reliably produce something weird. You tell them which functions were involved and when, and they tell the developers how to fix it quickly.

This type of when and where stuff becomes much easier when the inside of your app looks like a list of functions used at specific times. Suddenly, where and when translates into exact lines of code with exact input parameters and a list of things that went wrong. My QA brain is drooling over the prospect of those app and team efficiency gains.

Everything tends to be easier to reason about when everything is made from deterministic or at least unidirectional functions. If something appears to be wrong inside thegetUserProfile() function, there is probably only one place is your app called that, and it probably looks like a list of things to do when getting a user profile. This leads me to another area of discussion. When your app is about to make a change to something it knows about, you could call it a mutation of the app’s state, but you must go through a formal change process.

Formal Change Process

I know some of you are already thinking: this rascal is about to talk about Redux. Well, I go news for you — that is correct. People don’t use Redux because they love adding brutal to understand addons into an app. They use Redux because it proposes a series of mechanisms that guarantee the app never gets confused about a state change.

Change management is important like generally-one-way flow is important. Both of those are important like this animated GIF is important:

That’s actually what the inside of React looks like. Gear A is like the render function in your component, and JSX is the language used inside a render function. Get used to it. HTML and CSS can appear there, but do you know what is output from a render function? DOM elements. Holy cow, we just went from the top of your app to the bottom and hit the DOM. If something changes, your app will let your app know. No one will get confused.

In less sophisticated systems or more complex systems, data can more often travel backwards through the data flow. This adds efficiency but also delivers more complexity and potential confusion. It’s like adding turbulence. You know when you look at a flowing river around some rocks and you see those little whirlpool things, and you throw a stick in there because you’re a scientist? That is what added complexity looks like. You can navigate it, but it brings at the very least some serious considerations.

You cannot achieve peak flow velocity or efficiency in a given system if there is turbulence. Turbulence isn’t really a programming term, but it gives you mental imagery of non-deterministic types of things. If a change in direction relies on randomness, it’s probably not pure.

Network Calls

I’ve intentionally stayed mostly away from talking about things like network calls and asynchronous disk I/O because I only want to pile so many hundred new ideas into your brain at once. When you make a network call for some data, the server could respond with different output even though you gave it the same input.

Concurrency

Stacked on top of that, concurrency brings with it indeterminism. Why? Race conditions. If you always fire off three guns at the same time, there is no guarantee that all three bullets will hit the ground at the same time. Remember, wind, pressure gradient force, small birds — things you cannot account for may become a significant factor and result in unreliable results.

Both network calls and concurrency are why Redux exist and why it is extremely important to care about having a formal change process. Redux is the result of asking, “how can we reasonably guarantee a problem cannot occur?”

Listen, async/await is a beautiful thing when composing functions, but it does not fully save you from problems with concurrency. I didn’t want to talk about the event loop, but we are going to have to.

Rather than talk about that. I’ll get you to do some homework:

Pass-by-Reference & Garbage Collection

In JavaScript, two things are critically important to understand if you and I hope to write apps that care about proper memory use. These two things are related in that one helps with storing in memory and the other helps with cleaning the memory out.

If we don’t take care of the memory, we might get memory leaks. If you had a stream or a pipe under your sink, you don’t want to be using or allowing the word leak.

Pass-By-Reference

This can be explained in one quick animated GIF:

Fig ?.? — Live reference

If I modified the cup of coffee inside fillCup(), with pass-by-reference, I would be modifying the unique coffee cup (think Singleton). With pass-by-value, it’s a different cup of coffee even though it looks identical. This could be a blessing or a curse. Maintaining a live reference is great, but remember how shared mutable state is dangerous? Remember how side effects are dangerous? If the reference is live and real-time, to modify the cup could be to modify someone else’s coffee.

A Quick Test: Go try right now to modify your co-worker’s coffee and let me know if they are ok with it or if they have some kind of meltdown. Sometimes it’s ok. Sometimes it’s not. That is literally the best description I’ve ever heard for combining all these concepts. I don’t even care if you like it. I laugh at my own jokes.

Now, it is obvious, but not to someone, and that’s why I fly out of the woodwork to help them understand. It’s very nice of your City to clean up your garbage provided you were nice enough to leave it somewhere for them to pick it up. Something very similar is happening deep in the bowels of JavaScript, only there is no smell associated with it. I used to wash garbage trucks when I was younger, so you can trust me on that. Very funny, but cleaning details on garbage trucks sharpened my attention to detail in other areas of life, such as QA.

Garbage Collection

If you are maintaining references to things, you can quickly observe them, but you can also forget to release them from memory. This is garbage collection. When a function is done executing and there are no more references to that function, your app forgets about that function and dumps it out of the memory. It gets garbage collected. The City comes and takes that garbage away.

Functional Programming

Functional programming is essentially about breaking your program into manageable chunks but not just any chunks. A good chunk is probably based on an event or an action.

When might a function be executed, like when is a good time to fire one up?

  • before actions or events
  • during actions or events
  • after actions or events

3 Phases of a Function

  1. Detection and Collection Phase
  2. Packaging Phase
  3. Delivering Phase

These phases are not required by any means. I mention them to help you think about the types of things people do inside functions. A phase could be more known to you by a different name. That’s okay.

In the first phase, data comes into a function and gets analyzed. Think of this stage like bank of probe sensors from Star Trek. Before anyone feels comfortable doing anything, observations should probably be made. Things could be compared, etc. It’s just good science to operate this way.

In the second phase, work is done to process the data. You could imagine a direction has been selected and now the function is working towards that. You could imagine the function analyzed whatever it needed to, and now it’s performing it’s main function, no pun intended. It may sound like the delivering phase, but it’s not quite the home-stretch yet.

In the third phase, work has been completed, and now it is delivering the final product. Imagine a postal delivery truck driving at 30mph or 50km/h, and there is a happy driver in there, excited to deliver your result set.

Work

  • Power: Ability to complete a large body of work quickly
  • Torque: Ability to quickly start or stop work

Memory

  • Short term memory: Knowledge of context and working parameters
  • Long term memory: May be used alongside work or memory

Continuation-Passing Style (CPS)

This is a style of programming that is cleverly disguised as callbacks in JavaScript. The shortest possible definition involves a function waiting until it gets a signal to continue to the next function. You’ve seen it before. You’ve heard of callback hell. You’ve also seen it be consistently useful when you want some code to let some other code know when it is ready.

Keep an eye on callbacks because they let your app spend as much time as needed to finish some tasks before it moves on. Callbacks give you a reasonable guarantee that the next steps in a process will wait until all necessary data is available before beginning work. It’s like waiting for the materials to arrive at a job site before bringing in the construction crew.

In asynchronous JavaScript, if you are going to have a problem, it’s probably because something happened too soon or too late. It’s just the nature of the event loop game.

Here is a bit of a visual explanation:

Callbacks can seem a bit like they are flowing backwards because they exist at the top of a function where data came from, but a callback function is called while the data is flowing forward.

From the function in which the callback is called, it’s more like a button because the function has no idea what happens after the button is pressed. Why? Because the next moments in time are handled upstream in the parent function. It has to do with separating dimensional concerns.

Callbacks allow children to be involved while free of responsibility It means, if you changed the logic inside the child and the callback is still called correctly, the parent is not affected. It means, if you changed the logic in the parent, the child is not affected.

Monad

[define]

There are a few things that are very important towards our goal of protecting state’s integrity:

  • Pure functions
  • Side effects
  • Referential transparency
  • Immutability

Pure Functions

Side Effects

Immutability

I’m going to tell you right now, composing functions does not work in asynchronous environments when state is unpredictably changing. State cannot be assumed correct.

One way of thinking that is helpful is to consider making an app ask for the latest state before mutating it. Race conditions are probably your main concern because 2 functions modifying state at the same time is just straight up a dangerous situation. That is to say it can be.

You would need at least a formal process for handling these changes. If you are familiar with Redux, you understand. If you are familiar with Reactive JS, you are light years ahead of an inferior symbol.

Immutable functional programming is all about first-in first-out (FIFO). This FIFO concept matches up nicely with reactive programming because it gives us a way to think about problems using one-way flows. Pure functions give both referential transparency and a strategy that utilizes FIFO to handles state changes. If the scenario is complex, we may create one function to handle it or we may create a series of functions.

A series of inter-dependent functions is a chain of functions.

The real star of functional programming is composition. You take function that does one thing and call it from another function. Then, you call that function from a third function. Now, you are composing functions.

Composition

Composing functions isn’t a new thing. Without fact checking, I think people have been doing it for thousands of years in Mathematics. You may recall from math class:

  • f of x
  • g of x
  • f composed with g of x
Fig 5.1 — Function Composition

f composed with g of x written in JavaScript looks like this:

f(g(x))

It means:

  1. execute g(x)
  2. then, take the result of that
  3. then, pass that into f()

You can see how people might chain them together. Composition is among the key reasons why functional programming is becoming increasingly dominant. Our code becomes more declarative when we compose functions, and declarative code is often easier to understand. Declarative means you tell the program how to act and when, and it does it. It’s like showing a horse how to get water vs. giving it water every time it needs it.

When writing functionally, you:

  1. declare how your program should respond to various inputs (ie: define what actions the functions do),
  2. declare configuration settings that define what those inputs are (ie: define state at moments in time),
  3. declare when to trigger these functions (ie: define the events your program reacts to).

I selected those keywords very carefully. Moving on, we can compose not only functions but also objects when we are thinking this way. Here is an example:

const person = {
firstName: 'Suzy',
lastName: 'Kawasaki',
}
const config = {
host: '127.0.0.1',
port: 1337,
user: person,
}
const connectToDB = (config) => {
const connection = getDriver(config.host, config.port)
return connection
}

See how connectToDB() accepts the config object and how the person Object is composed inside the config Object?

Functional style code that is declarative can strike a near-perfect mix of declarative vs. imperative. Declarative means you tell it what to do. You declare it. Imperative means you tell it how to do it, which is like telling the function exactly how to operate. You need to do both. You can’t get away from both like you can’t get 100% away from Objects or Functions. There is always a mixture.

A function is like a module. It performs the work given to it by its parent. A function is also a component that is controlled by its parent. There could be limited control. The parent may say do whatever you determine is correct.

Functional + Reactive = Modular Components

The 3 tenants of modular components:

  • self-contained
  • accepts a Config Object
  • external Side Effects are officially managed
  1. single source of truth store/repository for standalone components
  2. pull packages into any project via NPM or equivalent

Self Contained

Components should be self-sufficient. I would go as far as to say they should be 100% self-sustaining as much as is reasonable. If it’s not self-sustaining, it’s dependent on something. The best components will handle all duties related to a specific event. This works because the component takes ownership of all sub-events and actions related to this event. If another component needs to push or pull anything, there should be an official process on both sides to handle it. Control is specifically delegated.

Config Objects

True to Functional Reactive ways of thinking, a config object should be pushed into the component. The component should require this object. The component uses it to drive all of its functions. Config Objects provide the necessary nutrition for optimal performance. They also allow the component to be used in any project simply by declaring parameters.

const config = {
one: 'value',
two: { complexData },
three: () => functions()
}
const Component = (config) => {
if (!config) throw new Error('Because reasons.')
// config can be used as desired
const { one, two, three } = config
return {
one,
two,
three,
}
}

asdf

External Side Effects

Simple, the root level of the component should not modify any external state. There is a permission boundary. These potential side effects occur when the component freely mutates parent state. There should be no reaching into other files and grabbing things. With respect to the Config Object, any required data should probably be pushed into the component. The component could also pull the necessary data in. This would be like a hook that allows the component to ask for state.

Here is a naive button; it could participate in any event:

const Component = (config) => {
const { onEvent, text, css } = config
return (
<button onClick={onEvent} style={css}>
{text}
</button>
)
}

In this above example, the Component says, “the first one to handle this event wins”. Some function in the parent scope handles both the response action and the text for the button. All this component actually does is provide a framework for making responses to Button pressing. Side Effects are critically required for this to work.

Side Effects are theoretically bad because they break referential transparency. Imagine you had a function called addTogether(1, 2) which always returns 3 but also changes the color of a background to blue. If someone didn’t know the background turned blue, they would be missing that secret knowledge that may only be known by observing a single line of code hidden somewhere.

Functional Reactive way of thinking would have us be aware of the propagation of change, and we would ensure there is an official process in the component to handle this. Not doing so is analogous to shady black market deals.

Here is an example of

asdf

JSX

I won’t leave you empty handed about JSX after reading all that. My thoughts can be summarized by this quote from Mark Dalgleish:

“What’s interesting, though, is that rendering to the DOM is not part of the core React library, instead being provided by react-dom.

import { render } from 'react-dom'

Even though React was built for the DOM first, and still gets most of its usage in that environment, this model allows React to target wildly different environments simply by introducing new renderers.

JSX isn’t just about virtual DOM — it’s about virtual whatever.”

Source: Mark Dalgleish (https://medium.com/seek-blog/a-unified-styling-language-d0c208de2660)

I’ll spare you the details about what JSX is. Mark captures why we care about it in the quote above. JSX represents something much bigger. In 2018, we are probably looking at the tip of the ice berg. I would encourage you to pay attention. JSX is just a notation. This custom renderer jazz is very important. I will leave it up to you to research further.

Remember, I do not seek to tell you exactly the right answer. I seek to show you some ways to reliably find the right answer. If you propose some changes, write an article. We can maintain a live reference to it from here. When you mutate it, I won’t have to update the live reference.

Recommended Next Steps

I recommend studying Neo4j because of relationships between data compared to relational databases. It is fundamentally different and a profound upgrade in some ways. I am a great fan of the unstructured data that fits nicely into algorithms and reveals vectors and intensity values.

If you disagree, that’s not my problem. If you agree, study related data because this free flowing, unstructured data type is a magical companion to Functional Reactive Programming. It’s kind of why GraphQL exists; because Facebook required to communicate with the Social Graph. That is only one type of graph. If that doesn’t blow your mind, then you are probably already sufficiently advanced at some concepts of your choosing.

This article will finish rendering at the next character in this sentence chain.

LET THESE PEOPLE KNOW

@mate0day

--

--

Adam Mackintosh

I prefer to work near ES6+, node.js, microservices, Neo4j, React, React Native; I compose functions and avoid classes unless private state is desired.