简体   繁体   中英

Very strange and unexpected problem about React components and this.setState()

I met an unexpected problem and can not solve it the second day, so I seek help here. Also, I should to mention that I use CoffeeScript 2.

I have a parent component ( Form ) and child components (form elements), the problem concerns one of the components (custom multiple options selector). Their work order is as follows: The form has this component that has props value set (an array of objects obtained from this.state form, initially this array is empty) and enterChange (handler which changes state, ie selected options).

The child element ( FormItem ), also has its own logic, has two states - view mode of the selected options and selecting mode. Each time you click on the option in selecting mode, this function is called (which causes the parent to update the data):

select: (option) =>
  if @props.config.multiple
    selected_options = @props.value
    already_exists = _.findWhere selected_options, { id: option.id }
    if already_exists
      options = _.reject selected_options, (object) -> object.id is option.id
    else
      options = [selected_options..., option]
    @props.enterChange options // here we pass an array of selected options.
  else
    @props.enterChange option
    @hideSelector()

And here is the handler of enterChange at the parent ( Form ):

selectActiveOptions: (options) =>
  # ask you to pay attention to this console.log
  console.log options # prints [undefined]
  @setState
    current_page: {
      @state.current_page...
      active_options: {
        @state.current_page.active_options...
        value: options
        valid: null
      }
    }

And now, here is what I get and what really surprises me: The state ( this.state.current_page.active_options.value which I use as value prop for FormItem ) turns into Array of undefined, for example, if I select three options, then I get [undefined, undefined, undefined] . But that's not all...

As you saw the console.log prints the same Array of undefined, BUT. If I disable the function this,setState: then the options variable is a normal array of objects! Here:

selectActiveOptions: (options) =>
  # ask you to pay attention to this console.log
  console.log options # prints [{ id: 'first', title: 'First' }]
  # @setState
  #   current_page: {
  #     @state.current_page...
  #     active_options: {
  #       @state.current_page.active_options...
  #       value: options
  #       valid: null
  #     }
  #   }

Also, if I don't use state value as prop of FormItem , then the state changes successfully (got Array of Objects), I don't understand what's at all. so I ask for your help me in this strange problem for me.....

I solved the problem, it was my mistake. The problems is in this part of code (FormItem):

<p className={ classNames 'value', 'placeholder': @props.value.length is 0 }>
  {
    if @props.value.length > 0
      value = @props.value
    else
      value = @props.placeholder # here is my mistake
    if typeof value is 'string'
      if @props.config.uppercase then value.toUpperCase() else value
    else
      value = @props.value
      value.map (item, number) ->
        value[number] = value.title # and here I made this "magic". (item but not value)
      value.join ', '
  }
</p>

But I still don't understand why.map changes this.props.value... So I created these changes:

<p className={ classNames 'value', 'placeholder': @props.value.length is 0 }>
  {
    if @props.value.length > 0
      value = @props.value
    else
      value = @props.placeholder # here is my mistake
    if typeof value is 'string'
      if @props.config.uppercase then value.toUpperCase() else value
    else
      titles = []
      value.map (item, number) ->
        titles[number] = item.title 
      titles.join ', '
  }
</p>

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