AnApprentice
AnApprentice

Reputation: 110950

Redux-Form, how to use formValueSelector with dynamic Field names?

I'm using redux form and trying to create a Field component like so:

<Rating
  stop={10}
  initialRate={selector(this.props.state, 'age')}
  onRate={(rate) => this.onRateChange(rate)}
  onChange={(value) => { this.changeRate("name", value) } }
/>
<span className="label label-default" id="label-onrate">{this.state.label}</span>

<Field
  name="age"
  type="number"
  component={renderField2}
/>

RateForm = reduxForm({
  form: 'rateForm'
})(RateForm);

const selector = formValueSelector('rateForm');

const mapStateToProps = state => {
  return {
  };
};

export default connect(mapStateToProps)(RateForm);

The problem I'm having is initialRate is not working... the following is not returning a value:

selector(this.props.state, 'age')

Because the field name will be dynamic, I need to avoid:

defining the specific field name in mapStateToProps.

What am I doing wrong with redux-form formValueSelector to not provide initialRate with a value?

Upvotes: 2

Views: 6188

Answers (3)

Luca Davanzo
Luca Davanzo

Reputation: 21520

@Ritesh points me out to the solution:

const formName = "form";
const form = reduxForm<MyFormFields, MyFormProps>({form: formName});    

function MyForm() {
   return (
     <div>
        Here your form
     </div
   );

}

const mapStateToProps = (state: any) => ({
    initialValues: {
    },
    getFormFieldValue: (field: string) => {
        const selector = formValueSelector(formName);
        return selector(state, field);
    }
});

const mapDispatchToProps = (dispatch: Dispatch) => ({
    changeField: (field: string, value: any) => dispatch(change(formName, field, value)),
    resetForm: () => dispatch(reset(formName)),
});

export default withRouter(connect(mapStateToProps, mapDispatchToProps)(form(MyForm)));

Hope this can be helpful for someone!

Upvotes: 0

Ritesh Bansal
Ritesh Bansal

Reputation: 3238

You can do something like this:

import { getFormValues } from 'redux-form/immutable'

getFormValues will return the values saved corresponding to the form name provided.

const mapStateToProps = state => {
  const formState = getFormValues('rateForm')(state)
  console.log('formState...', formState)
  return formState 
}

This is working fine for me. I am getting values of all the Field component rendered particular to this form i.e rateForm in your case. For more details, you can go here.

Upvotes: 2

Shubham Khatri
Shubham Khatri

Reputation: 281646

From the docs:

The function returned from formValueSelector() has the following structure:

selector(state:Object, ...field:String)

 state : Object [required]

The global Redux state given to mapStateToProps.

 ...field : String [required]

The field, or fields, you want to select. If you provide only one field name, the function will return the value of that field. If you provide more than one field name, it will return an object mapping fields to values. If your field are "deep" (i.e. has one or more . in the name), the structure you get back will also be deep. e.g. If your fields are 'a.b' and 'a.c', the resulting structure will be { a: { b:'bValue', c: 'cValue' } }.

In your case you are not returning anything from the mapStateToProps,

You could instead of having a selector in the Rating component, have it in mapStateToProps and use it like

<Rating
  stop={10}
  initialRate={selector(this.props.state, 'age')}
  onRate={(rate) => this.onRateChange(rate)}
  onChange={(value) => { this.changeRate("name", value) } }
/>


const selector = formValueSelector('rateForm');

const mapStateToProps = state => {
  return {
      state
  };
};

The above example is assuming that props are available to the Rating component.

Upvotes: 1

Related Questions