3

I have the following code:

main.js

submit(v) {
    console.log(v);
    const price = v.get("price");
  }

render() {  
<form onSubmit={handleSubmit(this.submit)}>
    <Field
    name="products"
    categoryId={categoryId}
    component={MyComponent}
    />

    <MySubmitComponent
    confirm={handleSubmit(this.submit)}
    />
  </form>
}

MyComponent.js

{this.props.products.map((product, index) => (
<ProductDetails
productId={product.productId}
price={product.price}
/>
))}

ProductsDetails.js

    <Field
    name="price"
    price={price}
    component={PriceText}
    initialValues
    />

    const selector = formValueSelector("products");
    const mapStateToProps = (state, ownProps) => {
      return {
        initialValues: { productId: ownProps.productId },
        productId: selector(state, "productId")
      };
    };
    ProductsDetails= connect(mapStateToProps)(ProductsDetails);

When I change the price of a product and press submit, the variable values in the submit function contains only the new price of the product without its productId. I also need the productId to inform the appropriate product. What do I miss?

Kathrine Hanson
  • 575
  • 2
  • 10
  • 32
  • Where do you maintain `products` and how you update the price? – huMpty duMpty Oct 15 '18 at 12:11
  • @huMptyduMpty I maintain products in a database and I update the price by clickling on the textfield. This is smt irrelvant as my main concern is that in a Field where I can only have one name with one value, I want to have another prop which is stable and does not change. This is the productId. Right now, when I am changing the price of a product and press the button Submit, I only take the new price without its productId. But without the productId I cannot handle the new price further. Is it possible to pass the productId as a unchangable prop in the Field? – Kathrine Hanson Oct 16 '18 at 07:30

2 Answers2

0

As far as I know and have used redux-form, one Field component will have only one value registered in the Store.

So you can approach it as having different multiple Forms, where each Form will have separate productId and price Fields. Once you submit the Form - you will have the both fields values.

Here's en example of creating multiple Forms.

According to your use case, it would be something like that:

Usage:

{ this.props.products.map(({ productId, price }, index) => (
  <Form form={`product-${productId}`} initialValues={{ productId, price }} />
/>
))}

<Form />:

const Form = reduxForm({
  // no need to put form again here as we are sending form props.
})(FormComponent);

<FormComponent /> - just the presentation component:

export const FormComponent = ({ handleSubmit }) => <form onSubmit={handleSubmit}>
  <Field
    name="price"
    component={PriceText}
  />
</form>
Jordan Enev
  • 16,904
  • 3
  • 42
  • 67
  • But I dont want to update the procuctId. I just want to pass it together with the priceId. PriceId can be changed but procuctId not. – Kathrine Hanson Oct 15 '18 at 12:19
  • Yep. It would be a hidden Field. Just registered in the Form. Doing it in that way - `productId` can't be updated, but both fields will be available on form submit. – Jordan Enev Oct 15 '18 at 12:20
  • This does not work. I need to change the content to see the value when I press submit. :-( – Kathrine Hanson Oct 15 '18 at 12:36
  • Just add `type='hidden'`. – Jordan Enev Oct 15 '18 at 12:38
  • This just hides the component. It does not change anything. – Kathrine Hanson Oct 15 '18 at 12:40
  • Oh yes. For all the forms you have to register `initialValues` where you will have to set the default value of `productId`. Doing this you won't need to render the hidden field. – Jordan Enev Oct 15 '18 at 12:42
  • You can separate the Form as a single component and pass it `productId` as props. Having `productId` prop - you can build the Form name dynamically and set it to `initialValues` too. [Something like that](https://stackoverflow.com/a/43535694/4312466). – Jordan Enev Oct 15 '18 at 12:45
  • @KathrineHanson I've added a complete example to the answer. Hope it guides and helps you. – Jordan Enev Oct 15 '18 at 13:13
  • Thanks a lot. It is diff than my approach but ur example is very good! – Kathrine Hanson Oct 15 '18 at 13:45
  • You're welcome. If the answer helped you somehow, you can accept / upvote it. Thanks :) – Jordan Enev Oct 15 '18 at 13:51
  • I edited my sample code. As you can see, only in the main.js I am using a form and I declare my submit function. I want to stay as it is and not do another form in a child component. – Kathrine Hanson Oct 16 '18 at 07:15
  • Okay. If you find out another solution, I would be happy to see your approach as answer. – Jordan Enev Oct 16 '18 at 08:16
  • Hi. I did smt more simple in construction but now I am facing this problem. I want to show some products. When you press a button, then the goForward() is called and you can see the next product. My problem is when the submit() is called, the values variable does not contain the current productId of the product that is shown. Instead of this, undefinied is shown. The problem in not only the undefinied value, but the productId has its initial value. What is wrong? – Kathrine Hanson Oct 17 '18 at 09:11
  • The strange is that the console.log in map props is called at the beginning once and shows the current productId. – Kathrine Hanson Oct 17 '18 at 09:13
0
class MyComponent extends Component {
  constructor(props) {
    super(props);
    this.state = {
        activeIndex: 0
    };
    this.submit = this.submit.bind(this);
    this.goForward= this.goForward.bind(this);
  }

  submit(values) {
    console.log(values);
  }

  goForward() {
    let index = this.state.activeIndex;
    let productsSize = products.length - 1;

    if (index === productsSize) {
      index = -1;
    }

    ++index;

    this.setState({
      activeIndex: index
    });
  }

  render() {
      <form onSubmit={handleSubmit(this.submit)} name="edit">
          {this.props.products.map((product, index) => (
          <ProductDetails
          productId={product.productId}
          price={product.price}
          />
          ))}
    </form>
  }


let MyProductComponent = reduxForm({ form: "edit" })(
  MyComponent
);

const mapStateToProps = (state, ownProps) => {
  console.log(formValueSelector("edit")(
        state,
        "activeIndex");
  return {
    initialValues: {
      productId: formValueSelector("edit")(
        state,
        "activeIndex"
      )
    }
  };
};

MyProductComponent = withRouter(
  connect(mapStateToProps)(toJS(MyProductComponent))
);
Kathrine Hanson
  • 575
  • 2
  • 10
  • 32
  • 1
    Please add details / documentation what are you doing. – Jordan Enev Oct 17 '18 at 09:33
  • I am showing the details of some products like price, size, color, etc. Each product is shown when you click on a button Next where the goForward() is called. You can also change the price of the procuct and a button Submit exists. My problem is when I press Next to see another product, the productId does not get the current value. It holds the initial value which is the productId of the first product(this.state = { activeIndex: 0 };). The function setState inside the goForward() is working. But why do I still get the initial value? – Kathrine Hanson Oct 17 '18 at 10:03
  • enableReinitialize prop helped a lot with undefinied but the state does not change. – Kathrine Hanson Oct 17 '18 at 10:04
  • I'm not sure I'm understand the problem correct, but it's an option to update the current product with `redux-form` `change` action creator` in `goForward` method. Here's an example: https://stackoverflow.com/questions/45230531/programatically-change-redux-form-field-value However I would recommend you to open a new detailed question, related to this problem only, because it's not related to the current question details. Please provide full details. – Jordan Enev Oct 17 '18 at 10:47
  • Also if you do it the way I mentioned in my answer, the product and price pair will be organized in a single form and you won't have such problem. Please try to understand my answer and give it a try. – Jordan Enev Oct 17 '18 at 10:55