预期 我想在选项卡的内容中加载一个加载状态,每当用户点击选项卡标题切换选项卡时,标记就会传递给子项。
问题 我有这个App组件,我使用setTimeout伪装它的api调用
class App extends Component {
state = {
loading: false,
data: []
}
getData = () => {
return new Promise(resolve => {
return setTimeout(() => {
resolve(
[
{
id: 1,
name: "Kelas A",
list: ["Jane", "Ali", "Ahmad"]
},
{
id: 2,
name: "Kelas B",
list: ["May", "Henry", "Ben"]
}
]
)
},500)
})
}
async componentDidMount() {
this.setState({
loading: true
})
const data = await this.getData()
this.setState({
data,
loading: false
})
}
//loadingComponent = () => <div>Loading...</div>;
render() {
const { data, loading } = this.state
return (
<Tabs
activeTab={1}
loading={loading}
//loadingComponent={this.loadingComponent()}
>
{data.map(o => (
<Tab
id={o.id}
>
<Tab.Title>{o.name}</Tab.Title>
<Tab.Content>
{o.list.join(", ")}
</Tab.Content>
</Tab>
))}
</Tabs>
);
}
}
我将加载状态作为prop传递给Tabs子组件,它工作,我可以看到真和假:
class Tabs extends Component {
static defaultProps = {
activeTab: 1
};
static getDerivedStateFromProps(nextProps, prevState) {
if(nextProps.loading !== prevState.loading){
return {
loading: nextProps.loading
}
}
}
state = {
activeTab: this.props.activeTab
};
changeTab = tab => {
this.setState({ activeTab: tab });
};
render() {
const { children } = this.props;
const { activeTab, loading } = this.state;
console.log('true or false before pass to children', loading)
return (
<div className="tabs">
{React.Children.map(children, child =>
React.cloneElement(child, {
loading,
activeTab,
changeTab: this.changeTab
})
)}
</div>
);
}
}
但是我把那个装载作为支柱传递给Tabs的孩子,这是Tab,加载标志变得虚假?我无法发现问题。
class Tab extends Component {
static Title = ({ children, tabId, activeTab, handleTabClick }) => {
return (
<div
className={`title ${tabId === activeTab ? "active" : ""}`}
onClick={handleTabClick}
>
{children}
</div>
);
};
static Content = ({ children, tabId, activeTab, loading }) => {
loading && 'Loading...' //won't work coz loading is always false, I wonder why
return tabId === activeTab ? (
<div className="content">{children}</div>
) : null;
};
render() {
return React.Children.map(this.props.children, child =>
React.cloneElement(child, {
handleTabClick: () => this.props.changeTab(this.props.id),
tabId: this.props.id,
activeTab: this.props.activeTab,
loading: this.props.loading // why always false?
})
);
}
}
答案 0 :(得分:0)
this.props.loading
始终为false
,因为它true
时甚至无法呈现,data
为loading
时true
为空{1}}因此data.map
不会创建任何组件。
即使data
为空,您也需要将加载检查移动到呈现的父组件。例如。 https://codesandbox.io/s/xpy3r3575z
编辑: 如果要为每个选项卡单独获取数据,则需要创建单独的API调用,一个用于获取选项卡标题以呈现选项卡标题,另一个用于获取活动选项卡的数据。
答案 1 :(得分:0)
最初将其设置为false
state = {
loading: false,
data: []
}
加载组件后,将其模拟为true,然后设置为false
async componentDidMount() {
this.setState({
loading: true
})
const data = await this.getData()
this.setState({
data,
loading: false
})
}
但您从未收到子组件中的组件状态更改。
您可以使用componentWillReceiveProps()
更改状态所以你可以尝试一下
class Tab extends Component {
componentWillReceiveProps(props) { //here you will get changes whenever state changes
let loading = props.loading
this.setState({loading});
}
render() {
return React.Children.map(this.props.children, child =>
React.cloneElement(child, {
handleTabClick: () => this.props.changeTab(this.props.id),
tabId: this.props.id,
activeTab: this.props.activeTab,
loading: this.state.loading //through state
})
);
}
}