Functional Hack

const add = a => b => a + b;
add(1)(2); // 3
add.js
const doubleThenAdd2 = pipe(multiply(2), add(2));
doubleThenAdd2(5); // 12
doubleThenAdd2.js
add(1, 2); // b => 1 + b;
addCallNormal.js
const add = curry((a, b) => a + b);
add(1); // b => 1 + b;
add(1, 2); // 3
add(1)(2); // 3
curriedAdd.js
const sort = (arr, algo = 'bubble') => // ... implementation
sort.js
const api = ({ url, method = 'GET', body = {}, headers = {} }) => // ...
implementation
api.js
const sort = curry((algo, arr) => // ... implementation );
sort('bubble', [5, 214, 23, 6]); // [5, 6, 23, 213]
const sortBubble = sort('bubble');
sortCurried.js
const doubleThenAdd2 = x => x |> multiply(2) |> add(2);
doubleThenAdd2F#.js
const doubleThenAdd2 = x => x |> multiply(2, ^) |> add(2, ^);
doubleThenAdd2Hack.js
const doubleThenAdd2 = x => x |> 2 * ^ |> 2 + ^;
doubleThenAdd2HackNoFunc.js
// Without `curry`
1 |> add(1)(%);
// With `curry`
1 |> add(1, %);
curriedWithHack.js
// From the README, w/ Hack pipe
const updated = state |> #{
...^,
counters[0].value: 2,
counters[1].value: 1,
metadata.lastUpdate: 1584383011300,
};
assert(updated.counters[0].value === 2);
assert(updated.counters[1].value === 1);
assert(updated.metadata.lastUpdate === 1584383011300);
deepSetRecord.js

Objects for related optional props

const Card = ({ heading, description, imageSrc }) => {
return (
<div className="card">
{imageSrc && <img src={imageSrc} />}
<h1 className="card-heading">{heading}</h1>
<p className="card-description">{description}</p>
</div>
);
};
Card.propTypes = {
heading: PropTypes.string.isRequired,
description: PropTypes.description.isRequired,
imageSrc: PropTypes.string,
};
CardNaive.js
const Card = ({ heading, description, imageSrc, imageAlt }) => {
return (
<div className="card">
{imageSrc && <img src={imageSrc} alt={imageAlt} />}
<h1 className="card-heading">{heading}</h1>
<p className="card-description">{description}</p>
</div>
);
};
Card.propTypes = {
heading: PropTypes.string.isRequired,
description: PropTypes.description.isRequired,
imageSrc: PropTypes.string,
imageAlt: PropTypes.string,
};
add-alt.js
const Card = ({ heading, description, imageSrc, imageAlt }) => {
return (
<div className="card">
{imageSrc && <img src={imageSrc} alt={imageAlt} />}
<h1 className="card-heading">{heading}</h1>
<p className="card-description">{description}</p>
</div>
);
};
Card.propTypes = {
heading: PropTypes.string.isRequired,
description: PropTypes.description.isRequired,
imageSrc: PropTypes.string,
imageAlt: PropTypes.string,
};
img-obj-prop.js

Top-Level Modules

import React from 'react';
import { getWidgets, createWidget } from '../widget';
export const WidgetView = ({ widgets }) => {
const [widgets, setWidgets] = useState([]);
useEffect(() => {
getWidgets()
.then(widgets => setWidgets(widgets));
}, []);
const onButtonClick = async () => {
await createWidget();
const widgets = await getWidgets();
setWidget(widget);
};
return (
<>
<ul>
{widgets.map(widget => (
<li key={widget.id}>{widget.name}</li>
))}
</ul>
<button onClick={onButtonClick}>Add widget</button>
</>
);
}
WidgetView.jsx
// src/widget/index.js
export { Widget } from './Widget.js';
export { getWidgets, createWidget, updateWidget, deleteWidget } from './api.js';
export { encoder, decoder } from './schema.js';
index.js

yuptypes

export const yuptypes = (schema) => {
const propTypes = {};
for (const key in schema.fields) {
propTypes[key] = function checkYupSchema(
props,
propName,
componentName,
location,
propFullName,
secret
) {
try {
schema.validateSyncAt(key, props, { strict: true });
return null;
} catch (err) {
return new Error(
`Invalid ${location} `${propName}` supplied to ${componentName};${err.message.replace(
key,
""
)}`
);
}
};
}
return propTypes;
};
yuptypes.js

useEffect dependency array issues

useEffect(() => {
refreshCart();
}, []);
useEffect-issue.js
const refreshCart = () =>
api.getCart().then(cart => setState(cart));
refreshCart.js
const refreshCart = useCallback(
() => api.getCart().then(cart => setState(cart)),
[],
);
refreshCart-useCallback.js
const refreshCartRef = useRef(null);
if (!refreshCartRef.current) {
refreshCartRef.current = () =>
api.getCart().then(cart => setState(cart));
}
useEffect(() => refreshCartRef.current(), []);
refreshCartRef.js
useEffect(() => {
refreshCart();
// refreshCart is recreated fresh, but we only want to
// do this on initial render, so we're going to provide
// an empty array here so it only runs once.
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
refreshCart-eslint-disable.js

TypeScript unknown with kefir-ajax

ajax$(...)
.flatMap(response => response.json())
.flatMap(body => // body is `unknown`
ResponseType.decode(body).fold<Observable<ResponseType, t.Error>>(
Kefir.constantError,
Kefir.constant,
)
)
validate.ts

Component Render Function

import React from 'react';
export const Form = ({ submit }) => {
const [value, setValue] = useState('');
const onSubmit = (e) => {
e.preventDefault();
if (value === '') return;
submit(value);
}
return (
<form onSubmit={onSubmit}>
<label htmlFor="input">Type</form>
<input id="input" value={value} onChange={e => setValue(e.target.value)} />
<button>Submit</button>
</form>
);
};
form.js
describe('Form', () => {
it('should not submit the form with an empty value', () => {
const submit = jest.fn();
const { getByText } = render(<Form submit={submit} />);
fireEvent.click(getByText('Submit'));
expect(submit).toHaveBeenCalledTimes(0);
});
it('should submit the form with value', () => {
const submit = jest.fn();
const value = 'a value';
const { getByText, getByLabelText } = render(<Form submit={submit} />);
fireEvent.change(getByLabelText('Type'), { target: { value } });
fireEvent.click(getByText('Submit'));
expect(submit).toHaveBeenCalledTimes(1);
expect(submit).toHaveBeenCalledWith(value);
});
});
form.spec.js
const renderForm = props => {
const { getByText, getByLabelText } = render(<Form {...props} />);
const getButton = () => getByText('Submit');
const getInput = () => getByLabelText('Type');
const fireButtonClick = () => fireEvent.click(getButton());
const fireInputChange = value => fireEvent.change(getInput(), { target: { value } });
return { getButton, getInput, fireButtonClick, fireInputChange };
};
renderForm.js
describe('Form', () => {
it('should not submit the form with an empty value', () => {
const submit = jest.fn();
const { fireButtonClick } = renderForm({ submit });
fireButtonClick();
expect(submit).toHaveBeenCalledTimes(0);
});
it('should submit the form with value', () => {
const submit = jest.fn();
const value = 'a value';
const { fireInputChange, fireButtonClick } = renderForm({ submit });
fireInputChange(value);
fireButtonClick();
expect(submit).toHaveBeenCalledTimes(1);
expect(submit).toHaveBeenCalledWith(value);
});
});
Form-with-renderForm.spec.js
it('should not submit the form if value changed to empty string', () => {
const submit = jest.fn();
const value = 'a value';
const { fireInputChange, fireButtonClick } = renderForm({ submit });
fireInputChange(value);
fireInputChange('');
fireButtonClick();
expect(submit).toHaveBeenCalledTimes(0);
});
Form-extra-test.spec.js
const renderForm = createRender({
defaultProps: () => ({ submit: jest.fn() }),
component: Form,
elements: queries => ({
button: () => queries.getByText('Submit'),
input: () => queries.getByLabelText('Type'),
}),
fire: elements => ({
buttonClick: () => fireEvent.click(elements.button()),
inputChange: value => fireEvent.change(elements.input(), { target: { value } }),
}),
});
renderForm-rtk.js
it('should not submit the form if value changed to empty string', () => {
const value = 'a value';
const { fire, props } = renderForm();
fire.inputChange(value);
fire.inputChange('');
fire.buttonClick();
expect(props.submit).toHaveBeenCalledTimes(0);
});
Form-rtk.spec.js

pipe-dom

import { query, addClass, append, on } from 'pipe-dom';
query('ul')
|> addClass('important-list')
|> append(
document.createElement('li')
|> addClass('important-item')
|> on('click', () => console.log('item clicked'))
)
example.js

Tagged Unions & Loading State

type State = {
items: Item[] | null;
error: Error | null;
};
const initialState: State = {
items: null,
error: null
};
const successState: State = {
items: response.data,
error: null
};
const errorState: State = {
items: null,
error: response.error
};
array-error-state.ts
if (state.items === null && state.error === null) {
return <UnloadedView />;
}
if (state.items !== null) {
return <LoadedView items={state.items} />;
}
// We can assume we're in the error state now
return <ErrorView error={state.error} />;
array-error-conditional.ts
type State = {
status: 'unloaded' | 'loading' | 'loaded' | 'error';
items: Item[] | null;
error: Error | null;
};
const defaultState: State = {
status: 'unloaded',
items: null,
error: null
};
status-state.ts
type State = {
loading: boolean;
items: Item[] | null;
error: Error | null;
};
const defaultState: State = {
loading: false,
items: null,
error: null
};
array-error-loading.ts
if (state.loading) {
return <LoadingView />;
}
if (state.items === null && state.error === null) {
return <UnloadedView />;
}
if (state.items !== null) {
return <LoadedView items={state.items} />;
}
return <ErrorView error={state.error} />;
array-error-loading-conditional.ts
switch (state.status) {
case 'unloaded':
return <UnloadedView />;
case 'loading':
return <LoadingView />;
case 'loaded':
return <LoadedView items={state.items} />;
case 'error':
return <ErrorView error={state.error} />;
}
status-conditional.ts
type First = {
tag: 'first';
prop: number;
};
type Second = {
tag: 'second';
value: string;
}
type FirstOrSecond = First | Second;
declare function getFirstOrSecond(): FirstOrSecond;
const thing: FirstOrSecond = getFirstOrSecond();
switch (thing.tag) {
case 'first':
// TypeScript knows prop exists and is a number.
// Accessing thing.value would cause an error.
return thing.prop + 1;
case 'second':
// And value exists and is a string here
return thing.value + ' came in second';
}
tagged-union.ts
type First = {
prop: number;
};
type Second = {
value: string;
};
type FirstOrSecond = First | Second;
declare function getFirstOrSecond(): FirstOrSecond;
const thing: FirstOrSecond = getFirstOrSecond();
// TypeScript complains about Second not having a `prop` property.
if (typeof thing.prop === 'number') {
// TypeScript does not know you have a First
// without an explicit cast
const prop = (thing as First).prop;
} else {
const value = (thing as Second).value;
}
union-fail.ts
type UnloadedState = {
status: 'unloaded';
};
type LoadingState = {
status: 'loading';
};
type LoadedState = {
status: 'loaded';
items: Item[];
};
type ErrorState = {
status: 'error';
error: Error;
};
type State = UnloadedState | LoadingState | LoadedState | ErrorState;
tagged-union-state.ts
type State = {
items: Item[];
};
const defaultState: State = {
items: []
};
array-state.ts

useOnEnter

import React, { useContext, useEffect } from 'react';
import { StdinContext } from 'ink';
export default function useOnEnter(onEnter) {
const { stdin } = useContext(StdinContext);
useEffect(() => {
const onData = data => {
const s = data.toString();
if (s === '\r') {
onEnter();
}
};
stdin.on('data', onData);
return () => {
stdin.off('data', onData);
};
});
};
useOnEnter.js