@vovikilelik/react-lens

Utils for lens implementations in react apps

Usage no npm install needed!

<script type="module">
  import vovikilelikReactLens from 'https://cdn.skypack.dev/@vovikilelik/react-lens';
</script>

README

It is the React implementation for lens-js

Wiki

Initialize

/* Lens core */
import { Lens, ... } from '@vovikilelik/lens-ts';

/* React implementation */
import { useLens, ...and more } from '@vovikilelik/react-lens';

Creation stateless components

You can create Lens component with using useLens() hook, whitch use like useState()

import { useLens } from "@vovikilelik/react-lens";

const Counter: React.FC = ({ lens }) => {
    const [count, setCount] = useLens<number>(lens);
    return <button onClick={() => setCount(count + 1)}>{ count }</button>
}

/* uses */
<Counter lens={lens.go('counter')} />

Creation statefull components

You can create an own class component extending LensComponent<L, P, S>, like React.Component<P, S>, where L is type of Lens node.

import { LensComponent } from "@vovikilelik/react-lens";

interface Props {
    className?: string;
}

export class Counter extends LensComponent<number, Props> {
    public render() {
        const {lens} = this.props;
        const {value} = this.state;
        return <button onClick={ () => lens.set(value + 1) }>{ value }</button>
    }
}

/* uses */
<Counter lens={lens.go('counter')} />

Third-patry components

Pattern of covering native components looks like:

import { createLensComponent, getHtmlLikeModel } from "@vovikilelik/react-lens";

const LensInput = createLensComponent<string>(
    <input />,
    getHtmlLikeModel()
);

Example of covering user component, like <Input text='' onTextChanged={} />

/* Any component */
interface Props {
    text: string;
    onTextChanged: (text: string) => void;
}
const Input: React.FC<Props> = (props) => { /* implementation */ }

/* Covering */
const inputModel = {
    getter: {name: 'text', mapper: v => v},
    setter: {name: 'onTextChanged', mapper: v => v}
}
const LensInput = createLensComponent<string, Props>(Input, inputModel);

/* Uses */
<LensInput lens={anyLens} />

Example

Make store.ts

import { LensUtils } from '@vovikilelik/lens-ts';

interface Store {
    counter: number;
}

export const lens = LensUtils.createLens<Store>({ counter: 0 });

Import and use

import { lens } from './store';
import { Counter } from './Counter';

const Application: React.FC = () => {
    const counterLens = lens.go('counter');

    return (
        <div>
            <div>Lens Component</div>
            <Counter lens={counterLens} />
        </div>
    )
}