Let’s take an example of a table component that allows actions like selection, sorting, etc.:
Currently, there are two approaches for implementing it, both of which have benefits and drawbacks:
Controlled - the benefits are full control over the component’s state and the ability to intercept actions and state. The downside is a lot of boilerplate to use the component as is.
Uncontrolled - the benefit is that it just works without added boilerplate. But the problem is that we have no knowledge or control over its internal state.
or: yikes, going back to view-controller using hooks
We write a controlled component, but we also export a controller that works out of the box, using hooks.
Here is a pseudo implementation:
export const DataTable = ({ data, selection, sorting, setSelection, setSorting, ... }) => (
// this is the controlled component implementation
...
)
export const useDataTableState = (initialSelection = {}, initialSorting = null, ...) => {
// here we implement the state management logic
const [selection, setSelection] = useState(initialSelection);
const [sorting, setSorting] = useState(initialSorting);
...
return {
selection,
setSelection,
sorting,
setSorting,
...
}
}
We separate the controlled component, which is just the view layer, from its state-manager, or ‘controller’ (and yes, I did it. I just used view-controller terminology :)) Then we export both, so that the user can enjoy both worlds.
Now, we can use the component and its state manager as is:
import { DataTable, useDataTableState } from ‘data-table’;
const MyComp = () => {
const dataTableState = useDataTableState();
return <DataTable {...dataTableState} data={ … }/>;
}
The added-value is that we are in control of the data table state, and we can use it, or decide to intercept some of its values / actions.
Here are some examples of using the controlled state:
import { DataTable, useDataTableState } from ‘data-table’;
const MyComp = () => {
const dataTableState = useDataTableState();
return (<div>
<DataTable {...dataTableState} data={ … }/>
<span>Selected { size(dataTableState.selection) } rows</span>
<button onClick={ dataTableState.setSelection({}) }>Clear selection</button>
</div>);
}
This approach could be beneficial for both open source writers, and for writing reusable components in your company