React组件会忽略显示空obj

时间:2018-11-07 20:56:39

标签: javascript reactjs

我有一个react组件,其方法是从一个对象读取一些数据,然后在另一个组件上返回有关其状态的文本。

问题在于,当应用程序最初加载时,obj长度最初将为0,而当对象数据加载时,则它将 更新,并且obj.length将大于0。

这是怎么回事:

Scenario 1 (obj will actually have data) 
      -- App Loading
      -- getTxt checks if obj is empty
      -- As data is not loaded yet on the first call obj.length will return 0 so 'No Data Found' is displayed
      -- Then when the app finishes loading it then updates and the obj.length > 0 so 'Found the data' is displayed

Scenario 2 (obj will be empty) 
      -- App Loading
      -- getTxt checks if obj is empty
      -- As data is not loaded yet on the first call obj.length will return 0 so 'No Data Found' is displayed
      -- Then when the app finishes loading it then updates and the obj is actually empty so it can stay the same.

我的问题是,如果在加载应用程序并重新检查obj.length后返回> 0,那么我不想显示第一个“未找到数据”, 但是我需要有一个条件,以防应用程序完成数据加载后数据仍然为0

代码如下:

import React from 'react'


class MyComponent extends React.Component {

    getTxt() {

        if (this.props.obj.length > 0) {
            return 'Found the data';
        } else if (this.props.obj.length == 0) {
            return 'No Data Found';
        }

            return 'Searching Data'
        }



    render() {
        return <SomeComponent text={this.getTxt()}/>
    }
}


export {MyComponent}

我该怎么做才能做到这一点?

3 个答案:

答案 0 :(得分:2)

如Felix Kling的评论所述。

您有三种不同的状态。

  1. 初始状态

  2. 无数据

  3. 有一些数据

初始状态会将data道具设置为null。收到数据后,它可以是空对象{}或具有某些信息的对象。

我可能会这样写:

class MyComponent extends React.Component {
  getStatus() {
    const { data } = this.props;
    if (data === null) {
      return "Searching data"
    }
    if (Object.keys(data).length === 0) {
      return "No data was found"
    }
    return "Found some data"
  }

  render() {
    return <SomeComponent text={this.getStaus()}/>
  }
}

这几乎是完美的,因为我想将逻辑与视图分开。我将使用化简器来获取数据,并根据其值/长度确定状态。

const statusReducer = (data) => {
  if (data === null) {
    return "Searching data"
  }
  if (Object.keys(data).length === 0) {
    return "No data was found"
  }
  return "Found some data"
}

class MyComponent extends React.Component {
  state = { data: null }
  componentDidMount() {
    getData()
      .then(resp => resp.json)
      .then(resp => this.setState({data: resp.data})
  }
  render() {
    return <SomeComponent text={statusReducer(this.state.data)} />
  }
} 

您可能会问将其传递给另一个函数(reducer)有什么意义?首先,正如我提到的,将逻辑与视图分开。其次,statusReducer可以在其他组件中重用。第三,更容易测试代码。

注意:我们只照顾幸福的道路。但是,如果请求有问题或响应包含错误,我们可能会得到错误的状态。

要处理这种情况,让我们看看另一种方法。让我们在data中有statusstate

class MyComponent extends React.Component {
  state = { data: null, status: 'PENDING' }
  componentDidMount() {
    getData()
      .then(resp => resp.json)
      .then(resp => this.setState({data: resp.data, status: 'COMPLETE'})
      .catch(err => this.setState(data: err.Message, status: 'ERROR'})
  }
  render() {
    switch(this.state.status) {
    case 'COMPLETE':
      return <SomeComponent text={statusReducer(this.state.data)} />
    case 'ERROR':
      return <ErrorComponent message={this.state.data} />
    case 'PENDING':
      return <Spinner />
    default:
      // there is a runtime/compiling error. 
      // Notify it in you console.log or something
      return null // Here I am silently failing but that's not a good practice
    }
  }
} 

如果将switch-case语句移到另一个函数并将其命名为loadReducer,我们甚至可以做得更好。但是,我会让您决定是否这样做。

也请注意Eitan的解决方案。他同时使用componentDidMountcomponentWillUpdate来更新status

答案 1 :(得分:1)

我同意费利克斯的评论。在功能组件中使用嵌套三元可能会更好。每当组件obj的道具更新时,组件也应更新。

export const myComponent = (props) => {
  return (
    <SomeComponent 
      text={ props.obj ?
        props.obj.length > 0 ?
              'Found Data'
            :
              'No Data Found'
          : 
            'Searching'
      }
    />
  )
}

答案 2 :(得分:1)


听起来好像您不想在接收到数据之前渲染任何东西?

我需要做的是使用组件状态来跟踪加载状态。安装组件后,将state.loading设置为true。

componentDidMount() {
  this.setState({loading: true})
}

在所有内容更新后,将load设置为false。

componentDidUpdate() {
  if (this.state.loading) {
    this.setState({loading: false})
  }
}

render函数中,根据加载状态有条件地进行渲染。

render() {
    const text = this.state.loading ? "Loading..." : this.getTxt()
    return <SomeComponent text={text}/>
}