【问题标题】:React JS: Component not updating, after calling setStateReact JS:调用 setState 后组件未更新
【发布时间】:2014-04-19 19:32:47
【问题描述】:

我正在玩一个小型的 react 应用程序,去了解库的窍门吧。该应用程序只是从服务器填充的一系列列表。单击列表项时,该项的值将添加到应用级别的列表过滤器中,然后将用于调用新数据以填充列表。

问题在于,即使调用setState,我似乎也无法让我的列表与来自应用程序(父级)的新数据相一致。这是我的代码(咖啡):

### 
@jsx React.DOM
###

{div, h1, h2, h4, ul, li, form, input, br, p, strong, span, a} = React.DOM

SearchApp = React.createClass
  handleTopItemClick: (filter) ->
    facet = filter.field
    filters = @state.filters
    if filters.facets[facet] and filters.facets[facet].length > 0
      filters.facets[facet].push filter.value
    else 
      filters.facets[facet] = [filter.value]

    strArr = []
    _.each filters.facets, (valArr, field) ->
      _.each valArr, (val) ->
        strArr.push "+(#{field}:\"#{val}\")" 

    @setState 
      filters: filters
      queryStr: strArr.join(' ').trim()

  getInitialState: ->
    filters:
      facets: {}
    queryStr: ''    

  render: ->
    (div {
      id: 'content'
      className: "search-wrap"
      },
      (h1 {}, "Search")
      (div
        id: 'widgets',
        (TopList
          title: 'Top Domains'
          params:
            query: @state.queryStr
            field: 'domain'
          onItemClick: @handleTopItemClick
        )
        (TopList
          title: 'Top Senders'
          params:
            query: @state.queryStr
            field: 'from'
          onItemClick: @handleTopItemClick
        )
        (TopList
          title: 'Top Recipient'
          params:
            query: @state.queryStr
            field: 'recipient'
          onItemClick: @handleTopItemClick
        ) 
      )        
    )

TopItem = React.createClass
  getDefaultProps: ->
    value: ''
    count: 0
    field: null

  render: ->
    (li {},
      (a {
        onClick: @handleClick
        className: 'top-item-filter'
        title: @props.value
        },
        (strong {}, @props.value)
        (span {}, @props.count)
      )
    )

  handleClick: (event) ->
    event.preventDefault()
    @props.onItemClick @props.value

TopList = React.createClass
  getInitialState: ->
    data: []
    params: @props.params

  componentWillReceiveProps: (nextProps) ->
    @setState params: nextProps.params

  componentWillMount: ->
    request.post("/facet").send(@state.params).end (results) =>
      @setState data: JSON.parse(results.text)

  render: ->
    itemNodes = _.map @state.data, (item) =>
      key = item.value
      TopItem
        value: item.value
        count: item.count
        key: key
        onItemClick: @handleItemClick

    (div {className: 'widget top-item'},
      (h2 {className: 'widget-header'}, "#{@props.title}")
      (ul {className: 'top-items-list'}, itemNodes)
    )

  handleItemClick: (value) ->
    @props.onItemClick
      value: value
      field: @props.params.field

React.renderComponent SearchApp(null), document.getElementById("content")

列表在第一次时都呈现良好,按预期获取未过滤的数据。当我点击一个列表项时,SearchApp 接收到事件,并相应地更新自己的状态。 componentWillReceivePropsTopList 类上被正确调用,但 setState 调用不会更新它们的状态,因此它们不会协调。我已验证 nextProps 包含新信息。我错过了什么?

【问题讨论】:

    标签: coffeescript reactjs


    【解决方案1】:

    没有任何理由将道具保存在状态中;并且将道具作为真相的来源更不容易出错。它还稍微简化了代码。

    不过,对于实际问题; componentWillMount 在这里只调用一次。如果要在传递新参数时重复 AJAX 请求;你可以这样做:

    TopList = React.createClass
      getInitialState: ->
        data: []
    
      getSearchResultsFromServer: (params) ->
        request.post("/facet").send(params).end (results) =>
          if @isMounted()
            @setState data: JSON.parse(results.text) 
    
      componentWillReceiveProps: (nextProps) -> @getSearchResultsFromServer nextProps.params
      componentDidMount: -> @getSearchResultsFromServer @props.params
    
      render: ->
        itemNodes = _.map @state.data, (item) =>
          key = item.value
          TopItem
            value: item.value
            count: item.count
            key: key
            onItemClick: @handleItemClick
    
        (div {className: 'widget top-item'},
          (h2 {className: 'widget-header'}, "#{@props.title}")
          (ul {className: 'top-items-list'}, itemNodes)
        )
    
      handleItemClick: (value) ->
        @props.onItemClick
          value: value
          field: @props.params.field
    

    理想情况下,您的 ajax 库将支持中止请求;并在 componentWillUnmount 中中止这些请求。

    【讨论】:

    • 做到了。非常感谢!正如你所建议的,我还通过道具删除了状态设置。
    猜你喜欢
    • 2020-02-12
    • 1970-01-01
    • 1970-01-01
    • 2022-11-22
    • 1970-01-01
    • 2018-09-20
    • 1970-01-01
    • 2019-04-09
    • 1970-01-01
    相关资源
    最近更新 更多