;
}
```
+Please note that if you are rendering an array that contains any primitive values (undefined, number, string) then the automatic keying will not be able to be as accurate as if you were to render an array of objects / arrays / class instances / sets / maps. This is because object references are used to track the movement of array elements through time, and primitive elements cannot be tracked in this way.
+
Array element forms can also opt-in to updates regarding their indexes using the `.useIndex()` hook.
If you'll be allowing users to re-order items in an array, then please note that you'll get better performance if array element components don't know about their indexes. If the `.useIndex()` hook is used, a element that has moved its position inside of its parent array will need to update, even if it is otherwise unchanged.
@@ -1214,7 +1220,11 @@ const dndReorder = (result) => (draft) => {
function DragAndDrop() {
const form = useDendriform({
- colours: ['Red', 'Green', 'Blue']
+ colours: [
+ {colour: 'Red'},
+ {colour: 'Green'},
+ {colour: 'Blue'}
+ ]
});
const onDragEnd = useCallback(result => {
@@ -1254,7 +1264,7 @@ function DragAndDropList(props) {
{...provided.draggableProps}
{...provided.dragHandleProps}
>
-
+
}
;
diff --git a/packages/dendriform-demo/components/Demos.tsx b/packages/dendriform-demo/components/Demos.tsx
index f097543..bf7d431 100644
--- a/packages/dendriform-demo/components/Demos.tsx
+++ b/packages/dendriform-demo/components/Demos.tsx
@@ -820,14 +820,18 @@ const offsetElement = (form: Dendriform, offset: number): void => {
function ArrayOperations(): React.ReactElement {
const form = useDendriform({
- colours: ['Red', 'Green', 'Blue']
+ colours: [
+ {colour: 'Red'},
+ {colour: 'Green'},
+ {colour: 'Blue'}
+ ]
});
const coloursForm = form.branch('colours');
const shift = useCallback(() => coloursForm.set(array.shift()), []);
const pop = useCallback(() => coloursForm.set(array.pop()), []);
- const unshift = useCallback(() => coloursForm.set(array.unshift('Puce')), []);
- const push = useCallback(() => coloursForm.set(array.push('Puce')), []);
+ const unshift = useCallback(() => coloursForm.set(array.unshift({colour: 'Puce'})), []);
+ const push = useCallback(() => coloursForm.set(array.push({colour: 'Puce'})), []);
const move = useCallback(() => coloursForm.set(array.move(-1,0)), []);
return
@@ -838,8 +842,11 @@ function ArrayOperations(): React.ReactElement {
const moveUp = useCallback(() => offsetElement(colourForm, -1), []);
return
-
-
+ {colourForm.render('colour', form => (
+
+
+
+ ))}
@@ -861,14 +868,18 @@ const offsetElement = (form, offset) => {
function MyComponent(props) {
const form = useDendriform({
- colours: ['Red', 'Green', 'Blue']
+ colours: [
+ {colour: 'Red'},
+ {colour: 'Green'},
+ {colour: 'Blue'}
+ ]
});
const coloursForm = form.branch('colours');
const shift = useCallback(() => coloursForm.set(array.shift()), []);
const pop = useCallback(() => coloursForm.set(array.pop()), []);
- const unshift = useCallback(() => coloursForm.set(array.unshift('Puce')), []);
- const push = useCallback(() => coloursForm.set(array.push('Puce')), []);
+ const unshift = useCallback(() => coloursForm.set(array.unshift({colour: 'Puce'})), []);
+ const push = useCallback(() => coloursForm.set(array.push({colour: 'Puce'})), []);
const move = useCallback(() => coloursForm.set(array.move(-1,0)), []);
return
;
}
```
+Please note that if you are rendering an array that contains any primitive values (undefined, number, string) then the automatic keying will not be able to be as accurate as if you were to render an array of objects / arrays / class instances / sets / maps. This is because object references are used to track the movement of array elements through time, and primitive elements cannot be tracked in this way.
+
Array element forms can also opt-in to updates regarding their indexes using the `.useIndex()` hook.
If you'll be allowing users to re-order items in an array, then please note that you'll get better performance if array element components don't know about their indexes. If the `.useIndex()` hook is used, a element that has moved its position inside of its parent array will need to update, even if it is otherwise unchanged.
@@ -1214,7 +1220,11 @@ const dndReorder = (result) => (draft) => {
function DragAndDrop() {
const form = useDendriform({
- colours: ['Red', 'Green', 'Blue']
+ colours: [
+ {colour: 'Red'},
+ {colour: 'Green'},
+ {colour: 'Blue'}
+ ]
});
const onDragEnd = useCallback(result => {
@@ -1254,7 +1264,7 @@ function DragAndDropList(props) {
{...provided.draggableProps}
{...provided.dragHandleProps}
>
-
+
}
;
diff --git a/packages/dendriform/test/Dendriform.test.tsx b/packages/dendriform/test/Dendriform.test.tsx
index c0b8b87..d614681 100644
--- a/packages/dendriform/test/Dendriform.test.tsx
+++ b/packages/dendriform/test/Dendriform.test.tsx
@@ -151,7 +151,13 @@ describe(`Dendriform`, () => {
describe('.index and .useIndex()', () => {
test(`should provide index and produce an update`, () => {
- const firstHook = renderHook(() => useDendriform(['a','b','c']));
+ const A = {id: 'a'};
+ const B = {id: 'b'};
+ const C = {id: 'c'};
+ const D = {id: 'd'};
+ const E = {id: 'e'};
+
+ const firstHook = renderHook(() => useDendriform([A,B,C]));
const form = firstHook.result.current;
const elementForm = form.branch(0);
@@ -160,7 +166,7 @@ describe(`Dendriform`, () => {
act(() => {
form.set(draft => {
- draft.unshift('x');
+ draft.unshift(D);
});
});
@@ -170,7 +176,7 @@ describe(`Dendriform`, () => {
act(() => {
form.set(draft => {
- draft.push('y');
+ draft.push(E);
});
});
@@ -552,7 +558,7 @@ describe(`Dendriform`, () => {
const formA = new Dendriform(123, {history: 100});
const formB = new Dendriform(123, {history: 100});
const formC = new Dendriform(123, {history: 100});
-
+
historySync(formA, formB);
formA.set(456);
@@ -592,7 +598,7 @@ describe(`Dendriform`, () => {
const formD = new Dendriform(123, {history: 100});
const formE = new Dendriform(123, {history: 100});
const formF = new Dendriform(123, {history: 100});
-
+
historySync(formA, formB);
historySync(formC, formD);
historySync(formC, formB);
@@ -612,14 +618,14 @@ describe(`Dendriform`, () => {
const formA = new Dendriform(123, {history: 100});
const formB = new Dendriform(123, {history: 100});
const formC = new Dendriform(123, {history: 200});
-
+
expect(() => historySync(formA, formB, formC)).toThrow('[Dendriform] All syncHistory() forms must each have a matching non-zero number of history items configured, e.g. {history: 10}');
});
test(`should error if passed zero history sizes`, () => {
const formA = new Dendriform(123, {history: 100});
const formB = new Dendriform(123);
-
+
expect(() => historySync(formA, formB)).toThrow('[Dendriform] All syncHistory() forms must each have a matching non-zero number of history items configured, e.g. {history: 10}');
});
@@ -628,7 +634,7 @@ describe(`Dendriform`, () => {
const formB = new Dendriform(123, {history: 100});
const formC = new Dendriform(123, {history: 100});
formC.set(456);
-
+
expect(() => historySync(formA, formB, formC)).toThrow('[Dendriform] syncHistory() can only be applied to forms that have not had any changes made yet');
});
@@ -3383,18 +3389,18 @@ describe(`Dendriform`, () => {
}
test(`should contain value`, () => {
-
+
const value: PluginValue = {
foo: true,
bar: true
};
-
+
const plugins = {
myplugin: new MyPlugin()
};
-
+
const form = new Dendriform(value, {plugins});
-
+
expect(initMock).toHaveBeenCalledTimes(1);
expect(initMock.mock.calls[0][0]).toBe(form);
@@ -3404,7 +3410,7 @@ describe(`Dendriform`, () => {
expect(pluginResult).toBe('0');
expect(pluginResult2).toBe('1');
expect(form.plugins.myplugin.state.calledTimes).toBe(2);
-
+
});
describe('useDendriform() with plugins', () => {
@@ -3413,9 +3419,9 @@ describe(`Dendriform`, () => {
const plugins = () => ({
myplugin: new MyPlugin()
});
-
+
const firstHook = renderHook(() => useDendriform(123, {plugins}));
-
+
const form = firstHook.result.current;
expect(form.plugins.myplugin instanceof MyPlugin).toBe(true);
});