Skip to content

Commit

Permalink
removed react-dom as peer dep
Browse files Browse the repository at this point in the history
  • Loading branch information
joepuzzo committed Apr 29, 2024
1 parent a70424a commit 6b1a378
Show file tree
Hide file tree
Showing 4 changed files with 180 additions and 2 deletions.
146 changes: 146 additions & 0 deletions ARRAY_FIELD_THOUGHTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
# How remove works

```
0, 1, 2, 3, 4, 5, 6, 7
a, b, c, d, e, f, g, h
Goal: remove d
EndState:
0, 1, 2, 3, 4, 5, 6, 7
a, b, c, e, f, g, h
------------------------------------------------
a -> stays
b -> stays
c -> stays
d -> gets removed
e -> moves from 4 to 3
f -> moves from 5 to 4
g -> moves from 6 to 5
h -> moves from 7 to 6
```

Next we need to consider how `informed` works.

`useField(“fieldName”)`

Which in the case of array fields is this

`useField(“arrays[3].fieldName”)`

**By Design** informed’s `useField` will trigger a `useEffect` anytime a fields name changes

**why?** because that is how its state is tracked and it must be re-registered under that new name

```js
// Register
useEffect(
() => {
if (isRelevant) {
// We already initialized before the render so the input exists in the form state, we need to redo after the render
logger('Register', name, metaRef.current);
formController.register(name, metaRef);
logger('Second Initialize', name);
formController.initialize(name, metaRef, false);
}
return () => {
logger('De-Register', name, metaRef.current);
formController.deregister(name); // <<<<<<<<<< THIS IS KEY !!!!!!!!!!!!
};
},
[name]
);
```

Inside of `FormController` this code is called ( basically tells it to no longer track this field under that name )

```js
deregister(name) {
debug('De-Register', name);
if (this.fieldsMap.get(name)) {
this.fieldsMap.delete(name);
this.emit('field', name);
}
}
```

In addition to the useEffect that triggers based on the fields `name` we also have a normal `useEffect` with **NO** dependencies

**What does this mean? When does this trigger?** It means we can have a `cleanup` function that we return from this `useEffect` that will clean up anytime this field gets unmounted

For normal use case of `un-rendering` a from field the above useEffect is GREAT! It does exactly what we want…

```js
// Cleanup on un-mount
useEffect(() => {
return () => {
// … some other code
formController.remove(metaInfo.name, metaInfo.keep, metaInfo); // <<<< IMPORTANT LINE ( tells form to remove this field! )
};
}, []);
```

**HOWEVER!** This is bad when we are performing an array field removal!

**WHY?** Because informed will try to perform a state removal of `“arrays[3].fieldName”` ( in our example field d ) but we DONT want to remove it from the form state… we want to `PULL IT` out of the array.

**The Solution** To solve this, we can tell the `FormController` to `lock` any removals that attempt to occur while the re-registration of all fields happens

In other words, the second the user clicks on the `Remove` for field d ( the field at index 3 ) we can tell the form to block any removals until all the fields have finished `re-registering`

**How do we know when that is done??** Simple, on user click of remove `d` ( at index 3 ) we simply take note on the length of our array ( in this case a, b, c, d, e, f, g, h is 8 )

So we know that e, f, g, and h all need to re-register under new names and that because our array is shrinking by a size of 1 we know that the last field to deregister will be at index 7

Therefore, we have code written to detect this located in `useArrayField` and that allows our form to unlock itself to allow future removals`

```
e -> moves from 4 to 3
f -> moves from 5 to 4
g -> moves from 6 to 5
h -> moves from 7 to 6 << Detect deregister on 7 and unlock
```

## Move

Now lets consider move(i, j)

Where i is the index of the field we want to move

And j is the location we want to move it to

```
0, 1, 2, 3, 4, 5, 6, 7
a, b, c, d, e, f, g, h
Goal: move h between d and e
EndState:
0, 1, 2, 3, 4, 5, 6, 7
a, b, c, d, h, e, f, g
------------------------------------------------
a -> stays
b -> stays
c -> stays
d -> stays
h -> moves from 7 to 4
e -> moves from 4 to 5
f -> moves from 5 to 6
g -> moves from 6 to 7
```

Notice how we have a similar scenario where e, f, g, and h will all be de registering

... now i need time to think ...

My initial thinking is we dont need lock because we are not removing anything

.. its possible that we may only need to create the move at the data structure level

i.e ObjectMap
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## 4.58.1 ( April 29th, 2024)

### Removed

- `react-dom` from peer deps as native app will yell at you :)

## 4.58.2 ( April 10th, 2024)

### Added
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,9 @@
"yup": "^0.28.1"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
},
"optionalDependencies": {
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
},
"nyc": {
Expand Down
26 changes: 25 additions & 1 deletion src/ObjectMap.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,19 @@ const ldSwap = (arr, a, b) => {
}
};

/* --------------------- move --------------------- */
const ldmove = (arr, fromIndex, toIndex) => {
if (Array.isArray(arr) && fromIndex < arr.length && toIndex < arr.length) {
const item = arr.splice(fromIndex, 1)[0];
arr.splice(toIndex, 0, item);
} else {
// Handle invalid operation more gracefully in real scenarios
console.warn(
`Attempted to move from ${fromIndex} to ${toIndex} but the operation is not valid.`
);
}
};

/* --------------------- has --------------------- */

// foo -->
Expand Down Expand Up @@ -285,7 +298,6 @@ export class ObjectMap {
return newObj;
}

// Very important ;)
static swap(object, path, i, j) {
// Get the path to the array
console.log('Swaping out out:', path, i, j);
Expand All @@ -297,6 +309,18 @@ export class ObjectMap {
ldSwap(arr, i, j);
}
}

static move(object, path, fromIndex, toIndex) {
console.log('Moving:', path, fromIndex, 'to', toIndex);
// Get the array at the specified path
const arr = ldget(object, path);
console.log('Array before move', JSON.stringify(arr));

// Use ldmove to perform the operation
ldmove(arr, fromIndex, toIndex);

console.log('Array after move', JSON.stringify(arr));
}
}

function cleanup(obj, path) {
Expand Down

0 comments on commit 6b1a378

Please sign in to comment.