0

I've got a component which can contain any number of child components, and I want these child components, which contain input fields, to set those input fields to "disabled" when the state in the parent is changed. I've been attempting to use React.cloneElement with React.Children.map to modify the properties of the child elements, but it doesn't seem to be affecting anything.

Here's a simplified version:

# parent component
# assume that there's a @setState call in here somewhere
DisableableItem = React.createClass
  getInitialState: ->
    disabled: false
  render: ->
    <div>
      {
        React.Children.map @props.children, (child) =>
          React.cloneElement child, isDisabled: @state.disabled
      }
    </div>

# child component
ParameterizedOption = React.createClass
  getInitialState: ->
    disabled: @props.isDisabled
  render: ->
    <div className="parameterized-option">
      <label>{@props.text}</label>
      <div className="input-group input-group-sm">
        <input type={@props.inputType or "text"} className="form-control"
          placeholder={@props.initialInput or "00.00"}
          disabled={@state.disabled}></input>
      </div>
    </div>

And rendering it like:

React.render <DisableableItem>
    <ParameterizedOption text="hey" isDisabled=false />
    <ParameterizedOption text="hey" isDisabled=false />
  </DisableableItem>, document.body

So I'm console.logging the output, and the state in the parent is getting modified when I want it to, but the children's props are not getting modified as I thought the React.cloneElement call would modify them (they're always false as they were at start). I've taken a look at these questions, but I don't think they really apply, since DisableableItem doesn't know what its children are until they're given to it in the call to React.render, so it can't put disabled={@state.disabled} as one of the children's properties.

How would I reach in and modify these children's state? Am I misunderstanding what cloneElement is supposed to do?

Community
  • 1
  • 1
cosmicexplorer
  • 523
  • 6
  • 15

1 Answers1

1

You're copying the props to the state, which is some bad mojo. (https://facebook.github.io/react/tips/props-in-getInitialState-as-anti-pattern.html)

Just bind props.disabled directly to the element instead of copying it over to state.


Your current code:

getInitialState: ->
    disabled: @props.isDisabled

This will only work if you ensure you update state.disabled in componentWillReceiveProps to reflect the new props.disabled passed in.

If you're deadset on doing it your weird way: https://jsfiddle.net/1t8ew85x/

Sam P
  • 1,821
  • 13
  • 26
  • 1
    Rad. It turns out in my actual code (separate from the simplified version) I had another component in between and I didn't forward the change in props to the item that was actually getting disabled, so I was trying to modify the state to see if that would fix it. Thanks for the mojo help. – cosmicexplorer Jul 14 '15 at 20:50