1

Problem is that I want use Redux and based on the edit toggle (product.editable) it should be checked if the text are editable.

But everything goes well until it reaches the point that I want to edit the value that is inside the input field.

I need someone who could help me to the right direction. I know the JSON cannot be modified directly, but how can I change the current value and then make it editable inside the input field. Keep in mind I am using dumb components.

Component:

let getProductList = productList.map((product, i) => {
  return (
    <div key={i}>   
      {product.editable ?   
        <div>
          <input name="title" ref={(input) => title = input} value={product.title}/>
          <input name="description" ref={(input) => description = input} value={product.description}/>
        </div>
      : 
        <div>
          <div>{product.title}</div>
          <div>{product.description}</div>
      </div>}
      <ProductButtons productId={product._id} index={i}/>
    </div>
  ) 
});

export const ProductButtons = ({ productId, index}) => {
  const dispatch = useDispatch();
  return (
    <div>
      <button onClick={() => dispatch(deleteItem(productId, index))}>Delete</button>
      <button onClick={() => dispatch(editItem(productId, index))}>Edit</button>
      <button onClick={() => dispatch(addItem(productId))}>Add</button>
    </div>
  )
}

Reducer:

case types.UPDATE_PRODUCT: {
  console.log('update')
  return {
    ...state,
    products: state.products.map((product, i) =>
      i == action.index
        ? {
            ...product,
            editable: product.editable == true ? false : true,
          }
        : product
    ),
  }
}
Ajeet Shah
  • 18,551
  • 8
  • 57
  • 87
Frontend employee
  • 719
  • 2
  • 12
  • 26

2 Answers2

1

I hope toggle from and to Edit and View mode is working for you.

Now if your question is:

How to modify the product details (title, description, etc.) after a particular product item is in edit mode?

Here is how you can do it:

  • Wrap your input fields in form, make it uncontrolled by using defaultValue instead of value
  • place a input button of type submit (it will let you submit the form by hitting ENTER in any field, hide it with CSS if you don't want to show it):
<form onSubmit={this.handleSubmit}>
  <input
    name="title"
    ref={this.title}
    defaultValue={product.title}
    // value={product.title}
  />
  <input
    name="description"
    ref={this.description}
    defaultValue={product.description}
    // value={product.description}
  />
  <input
    type="submit"
    value="submit"
    className="display-none"
    style={{ display: 'none' }}
  />
</form>

and handleSubmit function:

handleSubmit = (e) => {
  e.preventDefault()
  e.stopPropagation()

  // you can use event to read form field values
  console.debug(e.target.title.value)
  console.debug(e.target.description.value)

  // or use the element Ref you created 
  console.debug(this.title.current.value)
  console.debug(this.description.current.value)

  // Here, you can make API call or dispatch action to your redux to update the data
}

Few other points:

  • Provide some other value to key instead of index if possible, e.g. product id
  • You can use editable: !product.editable in your reducer instead of editable: product.editable == true ? false : true
  • Use id if possible to find which product to update in your reducer instead of index : (products.map((product, i) => i == action.index ?)
  • Use === to compare instead of ==, more on this
Ajeet Shah
  • 18,551
  • 8
  • 57
  • 87
  • 1
    Thanks, this is a quite extended explanation and I think the solution is that by using defaultValue it made the input field editable. Not sure why, but I run this app with a server client. – Frontend employee May 22 '20 at 22:27
  • 1
    When you set `value` attribute of a form element in react with some value (literal or variable), this value becomes [single source of truth](https://reactjs.org/docs/forms.html#controlled-components) of its value and would not change at UI until that source is changed. But `defaultValue` will provide the value to element only once at render, after that it won't control the value of element. – Ajeet Shah May 22 '20 at 22:40
0

you can try using the boolean value in readonly attribute of inputfield

<input readOnly={product.editable} />
Kesav
  • 151
  • 4