Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

πŸ’ˆ useFieldArray #768

Merged
merged 66 commits into from Jan 14, 2020
Merged

πŸ’ˆ useFieldArray #768

merged 66 commits into from Jan 14, 2020

Conversation

bluebill1049
Copy link
Member

@bluebill1049 bluebill1049 commented Jan 4, 2020

New custom hook for FieldArray:

✨ useFieldArray

https://codesandbox.io/s/react-hook-form-usefieldarray-vy8fv

  const { fields, append, prepend, remove, move, swap, insert } = useFieldArray({
    control, // optional
    name: "test"
  });

latest beta version: 4.5.0-beta.2

  • building the hook
  • unit test
  • automation
    • normal flow
    • with default values
  • website documenation

@codesandbox-ci
Copy link

codesandbox-ci bot commented Jan 4, 2020

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Latest deployment of this branch, based on commit cc58895:

Sandbox Source
vigorous-wescoff-lfnpi Configuration
React Hook Form - useFieldArray PR

@codesandbox-ci
Copy link

codesandbox-ci bot commented Jan 4, 2020

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Latest deployment of this branch, based on commit 7acf6f1:

Sandbox Source
zen-gagarin-hcvbt Configuration
React Hook Form - useFieldArray PR

@bluebill1049
Copy link
Member Author

Will add units and automation later as well

Copy link
Contributor

@JeromeDeLeon JeromeDeLeon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So far so good πŸ‘

append,
remove,
update,
insert,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it should be named as insertAt because insert is more like a generic term for insertion of values. Same goes with update

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think insert is fine, less text to type as well. we have TS support the type as the argument :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. Sounds good to me :) Thanks

import * as React from 'react';
import isUndefined from './utils/isUndefined';

const id = () =>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we could also name this generateId instead

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sounds good

};

const insert = (index: number, value: any) => {
setField([...fields.slice(0, index), value, ...fields.slice(index)]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it better than using splice?

const newFields = [...fields];
newFields.splice(index, 0, value);
setField(newFields);

or is it about fewer lines the better or referential integrity of the values?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I try to avoid splice cause it's a mutation, slice is always return new Array

setField(
isUndefined(index)
? []
: [...fields.slice(0, index), ...fields.slice(index + 1)],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

splice?

@JeromeDeLeon
Copy link
Contributor

Sorry for pushing the splice. I just want to know why you prefer it over the other?

@bluebill1049
Copy link
Member Author

Sorry for pushing the splice. I just want to know why you prefer it over the other?

all good :) i try to use slice if i can most of the time

@JeromeDeLeon
Copy link
Contributor

I thought it was better and all. Thanks for answering it up. :)

@bluebill1049
Copy link
Member Author

I thought it was better and all. Thanks for answering it up. :)

thank you for taking a review on it @JeromeDeLeon ❀️

@JeromeDeLeon
Copy link
Contributor

You're welcome :)

@JeromeDeLeon
Copy link
Contributor

Looks like we need to bump it up to 6.6kb. πŸ˜„

@bluebill1049
Copy link
Member Author

bluebill1049 commented Jan 4, 2020

dame it 🀧

@bluebill1049 bluebill1049 changed the title POC for useFieldArray useFieldArray Jan 4, 2020
kotarella1110
kotarella1110 previously approved these changes Jan 4, 2020
Copy link
Member

@kotarella1110 kotarella1110 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the late!
This looks good!

@bluebill1049
Copy link
Member Author

Sorry for the late!
This looks good!

thanks for taking a look @kotarella1110

@kotarella1110
Copy link
Member

kotarella1110 commented Jan 4, 2020

Would you like to be able to set prepend and append defaultValue?

@bluebill1049
Copy link
Member Author

bluebill1049 commented Jan 4, 2020

Would you like to be able to set prepend and apend defaultValue?

what do you mean @kotarella1110 ? are you refer to append(defaultValue)?

@kotarella1110
Copy link
Member

kotarella1110 commented Jan 4, 2020

Appended field value is not set after append in your codesandbox.

γ‚Ήγ‚―γƒͺγƒΌγƒ³γ‚·γƒ§γƒƒγƒˆ 2020-01-04 15 44 01

Is there a way to set this?

@bluebill1049
Copy link
Member Author

Appended field value is not set after apend in your codesandbox.

γ‚Ήγ‚―γƒͺγƒΌγƒ³γ‚·γƒ§γƒƒγƒˆ 2020-01-04 15 44 01

Is there a way to set this?

oh it should work try this beta version: react-hook-form@4.5.0-beta.1

@bluebill1049
Copy link
Member Author

oops looks like it's not working @kotarella1110 good pick up!!

@bluebill1049
Copy link
Member Author

bluebill1049 commented Jan 4, 2020

<Controller
  as={<input />}
  name={`test[${index}].name`}
  control={control}
  defaultValue={item.name}
/>

@kotarella1110 that should make it work for insert. I am working over update now

@bluebill1049
Copy link
Member Author

bluebill1049 commented Jan 4, 2020

hmmm i don't think we need update because it's really setValue

@bluebill1049
Copy link
Member Author

Still appears to be not displaying for me. Have you hit the refresh in the codesandbox preview? I sometimes find the state 'lingers' :).

read my comment above, i have updated the comment.

@simmo
Copy link

simmo commented Jan 13, 2020

oooooh πŸ‘€ just seen that if you hard reload my sandbox (I've added more test items to the array), the output from line 13 on DemoField.js renders a nested output (should it?), when you change the first array item (App.js - eg { name: "0" }, > { name: "a" }, sandbox reloads but output is no longer nested.

Copy link
Contributor

@JeromeDeLeon JeromeDeLeon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm! Just a minor clarifications and all πŸ‘ . Sorry, I haven't able to support this one until today. Thanks for those who tested it out. We avoided bugs before the final release. πŸ˜„

@@ -0,0 +1,2 @@
export default (name: string, searchName: string) =>
name.startsWith(`${searchName}[`);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is searchName not enough? I don't think anyone will use the name more than once.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

test
testmyname

safer to make sure it's an array :)

import isArray from './utils/isArray';
import { FieldValues, UseFieldArrayProps, WithFieldId } from './types';

export const appendId = <
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might as well move this to logic folder if that's good to you just for consistency πŸ˜‰ .

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will do :)


const swap = (indexA: number, indexB: number) => {
resetFields();
[fields[indexA], fields[indexB]] = [fields[indexB], fields[indexA]];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

πŸ‘ for using destructuring to swap values

@@ -985,6 +994,12 @@ export function useForm<FormValues extends FieldValues = FieldValues>({
defaultValuesRef.current = values;
}

Object.values(resetFieldArrayFunctionRef.current).forEach(
resetFieldArray =>
isFunction(resetFieldArray) &&
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it better than doing if-then statement?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

save few bytes here hehehe

@simmo
Copy link

simmo commented Jan 13, 2020

read my comment above, I have updated the comment.

Thanks @bluebill1049 my bad πŸ˜„

oooooh πŸ‘€ just seen that if you hard reload my sandbox (I've added more test items to the array), the output from line 13 on DemoField.js renders a nested output (should it?), when you change the first array item (App.js - eg { name: "0" }, > { name: "a" }, sandbox reloads but output is no longer nested.

I think this might be the cause of my undefined issue as the shape changes.

@bluebill1049
Copy link
Member Author

thanks a lot for the testing @simmo ❀️I will address @JeromeDeLeon's comments tmr morning. almost 12pm here now going to bed. catch you guys tmr. thank you all πŸŒ™

@thoughtassassin
Copy link

Looks good to me. It took me a while to understand that the indices in the fields map function are unique even if two of the indices share the same name. I am about to upgrade my project to use 4.5.0-beta.9. I'll report any issues here if I see any.

@thoughtassassin
Copy link

thoughtassassin commented Jan 13, 2020

I can't say for certain but I think useFieldArray is mutating my defaultValues. I'll try to post a codepen to see if I can replicate the behavior. I don't think seeing this earlier in beta.6. Also, when I pass in the defaultValues into useForm without useFieldArray I don't see the mutation.

Yeah it looks like something is very broken. When I pass an object like this to defaultValues in userForm:

  "userId": "52qsptmbzt7dxug4",
  "email": "dkrause@adobe.com",
  "firstName": "David",
  "lastName": "Krause",
  "mageId": "",
  "systemRole": "Admin",
  "envRoles": [
    {
      "envName": "dev",
      "envRole": "Admin"
    },
    {
      "envName": "prod",
      "envRole": "View Only"
    },
    {
      "envName": "Production",
      "envRole": "Admin"
    },
    {
      "envName": "stage",
      "envRole": "View Only"
    },
    {
      "envName": "stg",
      "envRole": "Contributor"
    }
  ]
}

When I getValues from that I get back:

{
  "firstName": "David",
  "lastName": "Krause",
  "email": "dkrause@adobe.com",
  "systemRole": "Admin"
}

My envRoles are completely gone. That wasn't happening before.

@simmo
Copy link

simmo commented Jan 13, 2020

@thoughtassassin Sounds like you're having the same issue as me. Are you on beta 11?

@bluebill1049
Copy link
Member Author

I can't say for certain but I think useFieldArray is mutating my defaultValues. I'll try to post a codepen to see if I can replicate the behavior. I don't think seeing this earlier in beta.6. Also, when I pass in the defaultValues into useForm without useFieldArray I don't see the mutation.

Yeah it looks like something is very broken. When I pass an object like this to defaultValues in userForm:

  "userId": "52qsptmbzt7dxug4",
  "email": "dkrause@adobe.com",
  "firstName": "David",
  "lastName": "Krause",
  "mageId": "",
  "systemRole": "Admin",
  "envRoles": [
    {
      "envName": "dev",
      "envRole": "Admin"
    },
    {
      "envName": "prod",
      "envRole": "View Only"
    },
    {
      "envName": "Production",
      "envRole": "Admin"
    },
    {
      "envName": "stage",
      "envRole": "View Only"
    },
    {
      "envName": "stg",
      "envRole": "Contributor"
    }
  ]
}

When I getValues from that I get back:

{
  "firstName": "David",
  "lastName": "Krause",
  "email": "dkrause@adobe.com",
  "systemRole": "Admin"
}

My envRoles are completely gone. That wasn't happening before.

can you try the latest beta?

@thoughtassassin
Copy link

@bluebill1049 is the latest beta.11?

@bluebill1049
Copy link
Member Author

@bluebill1049 is the latest beta.11?

yes quite few iterations over issues

@thoughtassassin
Copy link

@bluebill1049 working on it now. I think there may be an issue in my code. I am trying to isolate and identify it now.

What I am seeing is that I have a few inputs in one component and I have my field array elements in another. The component without the field array gets the components but then they disappear from the field array. However, when I comment out the component without the field array elements, the field array elements show just fine.

In the component that I have the other elements I have a wrapper around that component. It uses useFormContext. I think when that element is being initialized it is wiping out everything else.

I'll see if I can create a codesandbox to see if I can duplicate the behavior outside of my project. That having been said, I don't think that I am doing anything unusual.

I wasn't seeing this on Friday with version 6 but I think I may have started seeing before I even switched to beta.9. I am currently on beta.11 and seeing this behavior.

@bluebill1049
Copy link
Member Author

@bluebill1049 working on it now. I think there may be an issue in my code. I am trying to isolate and identify it now.

What I am seeing is that I have a few inputs in one component and I have my field array elements in another. The component without the field array gets the components but then they disappear from the field array. However, when I comment out the component without the field array elements, the field array elements show just fine.

In the component that I have the other elements I have a wrapper around that component. It uses useFormContext. I think when that element is being initialized it is wiping out everything else.

I'll see if I can create a codesandbox to see if I can duplicate the behavior outside of my project. That having been said, I don't think that I am doing anything unusual.

I wasn't seeing this on Friday with version 6 but I think I may have started seeing before I even switched to beta.9. I am currently on beta.11 and seeing this behavior.

Thanks for the update. See if u can reproduce in a code sandbox. I will take a look at it.

@bluebill1049
Copy link
Member Author

are you using the same name for the input? @thoughtassassin

@thoughtassassin
Copy link

@bluebill1049 Okay. So I am not crazy. I can reproduce this issue without any of the other components in my codebase. If it looks like I am doing something wrong please tell me:

https://codesandbox.io/s/react-hook-form-usefieldarray-8f2nd

You'll notice that if you delete the NonArrayFields, ArrayFields shows. But if NonArrayFields is there ArrayFields are not rendered. This codepen is reproducing the issue that I am seeing exactly. I don't think I was seeing this Friday.

@bluebill1049
Copy link
Member Author

Thanks will take a look at it :)

@bluebill1049
Copy link
Member Author

@thoughtassassin
Copy link

@bluebill1049 That fixed it! Thank you.

@bluebill1049
Copy link
Member Author

Cool! Once I fixed code review’s feedback, we are ready then

@bluebill1049
Copy link
Member Author

@kotarella1110 let me know if you still have any more review comments. aim to merge this tonight.

@kotarella1110 kotarella1110 self-requested a review January 14, 2020 03:04
@bluebill1049 bluebill1049 merged commit a6cbd94 into master Jan 14, 2020
@bluebill1049
Copy link
Member Author

Thanks everyone :) merged

@bluebill1049 bluebill1049 deleted the useFieldArray branch January 14, 2020 10:16
@bluebill1049 bluebill1049 added this to In progress in React Hook Form Jan 29, 2020
@bluebill1049 bluebill1049 moved this from In progress to Done in React Hook Form Jan 29, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Development

Successfully merging this pull request may close these issues.

None yet

5 participants