Nativebase: How do you integrate Picker & Radio Elements with redux-form and have them update correctly?

Created on 8 Dec 2016  ·  22Comments  ·  Source: GeekyAnts/NativeBase

Hi,

I'm using redux-form to handle my form states and I've been using NativeBase for cute components views. Thanks for that

Merging redux-form and Views Library is explained in redux-form here except they are using MaterialUI which i'm not using and so the problems with implementation appears.

I can use NativeBase <InputGroup /> Like

/** Outside Form class/Function whatever, but the Component holding the form **/
const renderVehicleName = ({ input, placeholder, meta: { pristine, touched, error } }) => (
    <ListItem>
        <InputGroup iconRight>
            <Icon name="ios-person" />
            <Input placeholder={placeholder} {...input} />
        </InputGroup>
    </ListItem>
);

/** Inside render **/
<Field name="vehicleName" placeholder="Vehicle Nickname" component={renderVehicleName} />

This works, but when it comes to Picker, Checkbox or Radio i don't know how <Field /> should look like.

I tried

/** Outside Form Component **/
 <Field name="selectVehicle" mode="dropdown" style={{left: 10}} component={renderVehicleSelect}>

    <Item label="Car" value="Car" />
    <Item label="Bus" value="Bus" />
    <Item label="Bajaji" value="Bajaji" />
    <Item label="Motorbike" value="Motobike" />
    <Item label="Camel" value="Camel" />

</Field>

/** Inside Form Component render() **/
const renderVehicleSelect = ({ input, label, meta: {touched, error}, children, ...custom }) => (

    <Picker {...input} selectedValue={input.value} onChange={(event, index, value) => input.onValueChange(value)} children={children} {...custom} />
);

Looks wrong? Yes, i thought so..

No errors, but it won't update or trigger anything when i select a value. Yes It opens a select box, but when i select say _Camel_ nothing happens.

Please can you help me on this, or make an implementation of how to decorate NativeBase Form inputs with redux-form.

Thank You.

Most helpful comment

Thank you so much @maotora! For people using NativeBase v2.2.0 and Redux-Form v6.8.0, here is how I setup the Field for Picker. Basically the idea is to hookup the input.value and input.onChange props properly to the Picker via Field.

<Field
    name="newLoanTerm"
    component={ renderPicker }
    iosHeader="Select one"
    mode="dropdown"
    format={ formatLoanTerm }
    parse={ parseLoanTerm }
>
    <Item label="30 Years" value="30" />
    <Item label="20 Years" value="20" />
    <Item label="10 Years" value="10" />
    <Item label="7 Years" value="7" />
</Field>

and here is the renderPicker function:

const renderPicker = ({ input: { onChange, value, ...inputProps }, children, ...pickerProps }) => (
  <Picker
    selectedValue={ value }
    onValueChange={ value => onChange(value) }
    { ...inputProps }
    { ...pickerProps }
  >
    { children }
  </Picker>
);

as you can see, we only care about onChange and value from the input prop.

At last, the format and parse functions for formatting the selected value to string and save the selected value to number in the redux store:

const formatLoanTerm = value => value.toString();
const parseLoanTerm = value => parseInt(value);

Note, if you store the value as string (e.g. "10") in the redux-form store, then you don't need to set the format and parse props.

If you are confused about the format and parse functions, see http://redux-form.com/6.8.0/docs/ValueLifecycle.md/.

Hope that helps.

All 22 comments

Hello hello!.. I solved this myself yeii!!

Well apparently i wasn't so wrong, but the redux-form example is web based and some fucntions have a different implementation when coming to react-native weird, not a surprise i suppose.

  1. The should be exactly as how i placed it there, No <Picker /> props is going inside <Field /> component and that's the situation in most of renderedComponents going inside <Field /> in compnent prop, unless for some specific cases as this Checkbox here .

  2. I mentioned above that some functions implementation is different in react-native and redux-form didn't explain that in it's examples but here is what i've found.

In this code sample

 const renderVehicleSelect = ({ input, label, meta: {touched, error}, children, ...custom }) => (

    <Picker {...input} selectedValue={input.value} onChange={(event, index, value) => input.onValueChange(value)} children={children} {...custom} />
);

Notice that i have an onChange={(event, index, value) => onValueChange(input.value) } which i did blindly without understanding that what redux-form was using in as onChange value was material-ui's function to trigger on change of <Select/ Picker /> component.

So it can now change to onValueChange={(event, index, value) => onChange(input.value)} we pass inside our NativeBase's <Picker onValueChange={...} /> prop there and inside we call redux-form's onChange(input.value) and pass in the input.

But and it's a big but this doesn't work!
Inside the

onValueChange= {(event, index, value) => 
    { 
       console.log(value); //- logs undefined! 
       return onChange(input.value); 

    }

as explained in the comment, this returns undefined which was a release to me, so i tried replacing and turns out, in react-native the onValueChange only has two params, (value, index) no event!.

So i made it look like this and it worked!

onValueChange= {(value, index) => 
    { 
       console.log('value: ' + value + ' index: ' + index); //- logs value & index! 
       return onChange(input.value); 

    }

So this worked for me and it's been a great lesson on intergrating these libraries.
I posted a gist for both files (wrong and working one) here didn't explain anything but there is also a <Checkbox /> implementation and the code is redable, someone may find it useful.

Thank you NativeBase, Peace out!

@maotora Thanks. This is really helpful.

Glad I contributed to such an awesome community!

Thank you so much @maotora! For people using NativeBase v2.2.0 and Redux-Form v6.8.0, here is how I setup the Field for Picker. Basically the idea is to hookup the input.value and input.onChange props properly to the Picker via Field.

<Field
    name="newLoanTerm"
    component={ renderPicker }
    iosHeader="Select one"
    mode="dropdown"
    format={ formatLoanTerm }
    parse={ parseLoanTerm }
>
    <Item label="30 Years" value="30" />
    <Item label="20 Years" value="20" />
    <Item label="10 Years" value="10" />
    <Item label="7 Years" value="7" />
</Field>

and here is the renderPicker function:

const renderPicker = ({ input: { onChange, value, ...inputProps }, children, ...pickerProps }) => (
  <Picker
    selectedValue={ value }
    onValueChange={ value => onChange(value) }
    { ...inputProps }
    { ...pickerProps }
  >
    { children }
  </Picker>
);

as you can see, we only care about onChange and value from the input prop.

At last, the format and parse functions for formatting the selected value to string and save the selected value to number in the redux store:

const formatLoanTerm = value => value.toString();
const parseLoanTerm = value => parseInt(value);

Note, if you store the value as string (e.g. "10") in the redux-form store, then you don't need to set the format and parse props.

If you are confused about the format and parse functions, see http://redux-form.com/6.8.0/docs/ValueLifecycle.md/.

Hope that helps.

@jeantimex: I have a problem with your solution (code in the referenced ticket): The store is updated correctly, but the picker shows the wrong (first) option. Any idea why?

@luklapp, I see you are using redux-form/immutable, what if you try redux-form without immutable, would that work?

@jeantimex I'm using immutablejs in the whole application, so it would be good to get it working with redux-form/immutable!

I'm getting the same issue without immutable.js. After some updates in the picker value, the store starts to skip some update value. Here is my code:

<Field name="categoria" component={RenderPicker} > {categories.map(val => <Picker.Item label={val} key={val} value={val}/> )} </Field>

<Picker prompt='Selecione' selectedValue={ value } onValueChange={ value => onChange(value)} > { children } </Picker>

@michaelnagy I found a solution without using the Field component, you can find it here: https://github.com/erikras/redux-form/issues/3243

Hello @maotora
The checkbox gist example it's no longer available. You have this example yet?

Thank you!

Hi @donnes

Really sorry man, I accidentally deleted all my gists!
I will recreate it if it is really needed as I can see there are some better suggestions on this thread already.

Or you can explain your issue a little better for all subscribers to understand it and help.

@maotora

I think it's not a exactly a issue.
I just don't understood how implements the Redux Form with Radio and Checkbox because this components don't have the value property and the Field component from Redux Form requires it. I don't know how get the value from selected Radio/Checkbox exactly because they don't have this property.

Another question is how you implemented Radio Groups (Just a single radio can be selected if they are at same group)?

Sorry if this question sounds much simple.
Thank you!

@donnes I'm struggling with using Radio Buttons myself. Any progress?

Hey guys, I thought I should re-create the gist.

Link: here

Here is how I did it back in 2016 with "native-base": "^0.5.15" & "redux-form": "^6.3.2".
@donnes , @nonameolsson .

Goodluck!

Wow! Thank you very much @maotora
It will help me a lot!

@donnes Thanks man. 👍

Thanks!! Is it also possible to integrate with Radio Buttons? I couldn't
see how to so that. All help appreciated.
On Sat, 2 Sep 2017 at 11:41, ᕙ(⇀‸↼‶)ᕗ notifications@github.com wrote:

Closed #349 https://github.com/GeekyAnts/NativeBase/issues/349.


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/GeekyAnts/NativeBase/issues/349#event-1232382210, or mute
the thread
https://github.com/notifications/unsubscribe-auth/ABbIGjp1MfItSSJBVSrRW65GZDXT1szBks5seYUpgaJpZM4LHvEi
.

>

Andreas Olsson
(+46)70 - 090 42 72

I'm pretty sure it's simple @nonameolsson
If you check on my gist from this line for the checkbox example and check nativebase Radio Buttons api here swap checkbox's checked with Radio button's selected attr.

Well, Theoretically

@maotora Thanks for your help! Your Gist helped me. The thing is that RadioButtons only can have one selected, and checkboxes can have many. So I created a component that manage the state, and renders the radio buttons.

Here is my Gist: https://gist.github.com/nonameolsson/88b4f2349719f4657ae659d76e496d28

I hope it can help someone else. And if you have any idea how to improve the code I would appreciate it!

@jeantimex I have used your solution. Everything seems to be working except the default selectedValue is undefined. If I don't use the picker, the default value is not taken. onValueChange works as expected. tested on android.

<Field name={'gender'} component={renderGenderPicker} iosHeader="Select one" mode="dropdown" > <Item label="Male" value="male" /> <Item label="Female" value="female" /> </Field>

const renderGenderPicker = ({ input: { onChange, value, ...inputProps }, children, ...pickerProps }) => ( <Picker selectedValue={value} onValueChange={value => onChange(value)} {...inputProps} {...pickerProps} > { children } </Picker> );

@nonameolsson I got idea from you. and created new component. Here is my gist: https://gist.github.com/nazrdogan/b57f292d9f5c115f254094e3d13def17

@maotora still confuse with radio box, can help me with some example? Thanks

Was this page helpful?
0 / 5 - 0 ratings