Lenses in React
Uses TypeScript and Proxy to dynamically construct a lens-like interface for your application state.
Example
You can construct a lens/React Provider by just providing the shape of your application state
// LensProvider.ts
import { create } from "react-lenses";
import type { State } from "./application-state";
const { LensProvider } = create<State>();
export { LensProvider };
The lens itself is provided via a children
function to LensProvider
. This is an intentional decision to encourage using the lens as a prop from the root of your application UI.
// App.tsx
import type { State } from './application-state';
import { Root } from './Root';
import { LensProvider } from './LensProvider';
export const App = () => {
const state: State = { ... };
<LensProvider value={state} onChange={...}>
{lens => {
<Root state={lens} />
}}
</LensProvider>
}
The lens can be focused by regular member access.
// Root.tsx
import { Lens } from "react-lenses";
import type { State } from "./application-state";
import { Profile } from "./Profile";
type Props = {
state: Lens<State>;
};
export const Root = (props: Props) => {
return <Profile state={props.state.user.profile} />;
};
And then the underlying data it can be accessed by collapsing the lens into a React hook with useState
.
// Profile.tsx
type Props = {
state: Lens<{ name: string; email: string }>;
};
const Profile = (props: Props) => {
const [profile, setProfile] = props.state.useState();
return <input type="text" value={profile.name} onChange={(ev) => setProfile(ev.target.value)} />;
};