我有一个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}
我该怎么做才能做到这一点?
答案 0 :(得分:2)
如Felix Kling的评论所述。
您有三种不同的状态。
初始状态
无数据
有一些数据
初始状态会将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
中有status
和state
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的解决方案。他同时使用componentDidMount
和componentWillUpdate
来更新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}/>
}