简体   繁体   中英

Redux-Form update field value from external interaction

I have a redux-form connected to my application state and everything seems to work great. I can fetch data and load it into my form, then submit data and get the metadata I want...

However, I have a custom interaction (a color picker) that needs to change the value of a managed Field on the fly. Everything I try will change the screen, but not the redux form state ie when I submit the form I just get the original field data and not the new data shown in the form.

The version below is passing the field props to the component and trying to use the ColorSelect component state as the field value. I have also tried creating an action creator, but same result and much much more code that this example...

Note: react@^15.4.2, react-redux@^5.0.2, redux-form@^6.4.3

ES6: CollectionForm.js

 ... import ColorSelect from './ColorSelect'; class CollectionForm extends Component { /** * On form submit accepted * @param values */ onSubmit(values){ //See screenshot for evidence log('Updating collection:', 'warn', values); //values.color is grey and not yellow! this.props.dispatch(updateCollection(values)); return; } /** * Form render * @return {JSX} */ render() { const { handleSubmit, submitting } = this.props; return ( <form onSubmit={handleSubmit(this.onSubmit.bind(this))}> <Field component={renderTextInput} name="name" type="text" label="Name"/> <Field component={ColorSelect} name="color" /> <div class="field-buttons right-align group"> <Button type="submit" disabled={submitting} primary> Save </Button> </div> </form> ); } }; //Redux form decorator CollectionForm = reduxForm({ form: 'collectionForm' })(CollectionForm) // State connector CollectionForm = connect( state => ({ initialValues: state.collections.activeCollection }), //MapStatetoProps { onLoad: fetchCollection } //mapActionToProps )(CollectionForm); export default CollectionForm;

ES6: CollectionForm.js

 import React, { Component } from 'react' import { Field, reduxForm, SubmissionError } from 'redux-form'; const colors = [ 'grey', 'green', 'yellow', 'orange', 'red', 'purple', 'blue' ]; export default class ColorSelect extends Component { constructor(props){ super(props); this.state = { selectedColor : this.props.input.value //Set to current <Field> input value }; this.onSelect = this.onSelect.bind(this); this.renderColor = this.renderColor.bind(this); } /** * Color picker selected * @param color */ onSelect(color){ this.setState({ selectedColor: color }); //Sets correct state here } /** * Render a color list item * @param color * @return {JSX} */ renderColor(color){ const select = this.state.selectedColor === color ? "active" : ""; const klass = color + " " + select; return <li key={color}> <a class={klass} onClick={(event) => this.onSelect(color)}></a> </li> } /** * Render color list action * @return {JSX} */ render(){ //Override field value with colorSelected state return ( <div> <input {...this.props.input} value={this.state.selectedColor} name="color" type="text" label="Color" /> <div class="color-selector"> <ul> {colors.map((color) => this.renderColor(color) )} </ul> </div> </div> ); } }

You can use react-redux's mapDispatchToProps together with the change action creator in order to achieve what you want:

import { Component } from "react";
import { connect } from "react-redux";
import { change } from "redux-form";

class ColorSelect extends Component {
  // ...other stuff in this class...

  renderColor (color) {
    const { selectColor } = this.props;
    return <li key={color}><a onClick={() => selectColor(color)}></a></li>;
  }
}

export default connect(null, {
  selectColor: color => change( "yourFormName", "yourFieldName", color )
})(ColorSelect)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM