嗨,很抱歉我的英语不好。我正在使用react和redux。我在布局组件中调度getTags操作。问题是在调用getData操作之后,在渲染组件之后调用getDataSuccess操作。所以我的数据为空。如何确保数据被提取并呈现我的组件?
布局:
function DashboardLayout({
children,
showSideBar,
backgroundColor,
getTagsFromServer,
getCategoriesFromServer,
}) {
getTagsFromServer();
getCategoriesFromServer();
return (
<StyledDashbordLayout>
<NavBar />
<SideBarDrawer />
<Grid container className="container">
{showSideBar && (
<Grid item className="sidebar-section">
<SideBar />
</Grid>
)}
<Grid item className="content">
{children}
</Grid>
</Grid>
</StyledDashbordLayout>
);
}
DashboardLayout.propTypes = {
children: PropTypes.node.isRequired,
showSideBar: PropTypes.bool.isRequired,
backgroundColor: PropTypes.string,
getTagsFromServer: PropTypes.func,
getCategoriesFromServer: PropTypes.func,
};
function mapDispatchToProps(dispatch) {
return {
dispatch,
getTagsFromServer: () => dispatch(getTags()),
getCategoriesFromServer: () => dispatch(getCategories()),
};
}
const withConnect = connect(
null,
mapDispatchToProps,
);
export default compose(withConnect)(DashboardLayout);
传奇:
import { call, put, takeLatest } from 'redux-saga/effects';
function* uploadVideo({ file }) {
try {
const { data } = yield call(uploadVideoApi, { file });
yield put(uploadFileSuccess(data));
} catch (err) {
yield put(uploadFileFail(err));
}
}
function* getTags() {
const { data } = yield call(getTagsApi);
console.log(data, 'app saga');
yield put(getTagsSuccess(data));
}
function* getCategories() {
const { data } = yield call(getTCategoriesApi);
yield put(getCategoriesSuccess(data));
}
// Individual exports for testing
export default function* appSaga() {
yield takeLatest(UPLOAD_VIDEO, uploadVideo);
yield takeLatest(GET_TAGS, getTags);
yield takeLatest(GET_CATEGORIES, getCategories);
}
这是我的选择框组件,它从存储中获取空数据:
import React, { useState } from 'react';
function UploadFileInfo({ tags, categories }) {
return (
<Paper square className={classes.paper}>
<Tabs
onChange={handleChange}
aria-label="disabled tabs example"
classes={{ indicator: classes.indicator, root: classes.root }}
value={tab}
>
<Tab
label="مشخصات ویدیو"
classes={{
selected: classes.selected,
}}
/>
<Tab
label="تنظیمات پیشرفته"
classes={{
selected: classes.selected,
}}
/>
</Tabs>
{tab === 0 && (
<Grid container className={classes.info}>
<Grid item xs={12} sm={6} className={classes.formControl}>
<label htmlFor="title" className={classes.label}>
عنوان ویدیو
</label>
<input
id="title"
type="text"
className={classes.input}
onChange={e => setValue('title', e.target.value)}
defaultValue={data.title}
/>
</Grid>
<Grid item xs={12} sm={6} className={classes.formControl}>
<SelectBox
onChange={e => setValue('category', e.target.value)}
value={data.category}
label="دسته بندی"
options={converItems(categories)}
/>
</Grid>
<Grid item xs={12} className={classes.textAreaWrapper}>
<label htmlFor="info" className={classes.label}>
توضیحات
</label>
<TextField
id="info"
multiline
rows={4}
defaultValue={data.info}
variant="outlined"
classes={{ root: classes.textArea }}
onChange={e => setValue('info', e.target.value)}
/>
</Grid>
<Grid item xs={12} sm={6} className={classes.formControl}>
<SelectBox
onChange={e => {
if (e.target.value.length > 5) {
console.log('hi');
setError(
'tags',
'تعداد تگ ها نمی تواند بیشتر از پنج عدد باشد',
);
return;
}
setValue('tags', e.target.value);
}}
value={data.tags}
label="تگ ها"
options={converItems(tags)}
multiple
onDelete={id => deleteTagHandler(id)}
error={errors.tags}
/>
</Grid>
</Grid>
)}
{tab === 1 && 'دومی'}
<Dump data={data} />
</Paper>
);
}
const mapStateToProps = createStructuredSelector({
tags: makeSelectTags(),
categories: makeSelectCategories(),
});
const withConnect = connect(
mapStateToProps,
null,
);
export default compose(withConnect)(UploadFileInfo);
问题摘要
如果我正确理解你的问题,那么你是在问,当数据尚未提取时,如何在UploadFileInfo
中的SelectBox
中保护选项options={converItems(tags)}
的传递不受null
或undefined
值的影响。
解决方案
有几个选项可用于防范null
或undefined
值。
最简单的方法是为tags
提供默认的回退值。在这里,我假设tags
是一个数组,但它们可以是任何东西,所以请根据您的需求进行调整。
- 通过
options={converItems(tags || [])
或options={converItems(tags ?? [])
时联机 - 函数签名
function UploadFileInfo({ tags = [], categories })
- 作为
makeSelectTags
中回退返回值的一部分
另一种常见模式是条件渲染,其中null
可能是初始的redux状态值,因此您只需等待不为null即可渲染UI。
-
如果没有标签,则提前返回null
function UploadFileInfo({ tags, categories }) { if (!tags) return null; return ( <Paper square className={classes.paper}> ...
-
条件渲染
SelectBox
{tags ? ( <SelectBox ... /> ) : null }
关于在DashboardLayout
中获取数据调用的旁注
当您将函数调用直接放置在函数体中时,它们将在反应决定";渲染";执行任何DOM困难等的组件,几乎在DashboardLayout
渲染数据提取的任何时候都会进行,这可能会产生意想不到的影响。出于这个原因,反应功能组件体被认为是没有副作用的纯功能。将任何数据获取调用放置在一个效果挂钩中,该挂钩在组件装载时仅调用一次(如果在其他特定条件下需要调用,则为适当的依赖项(。
useEffect(() => {
getTagsFromServer();
getCategoriesFromServer();
}, []);
使用您的函数调用React.useEffect.内部的API
所有API调用都应该在useEffect
钩子内。有关useEffect的更多信息,请阅读此
function DashboardLayout({
children,
showSideBar,
backgroundColor,
getTagsFromServer,
getCategoriesFromServer,
}) {
React.useEffect(() => {
getTagsFromServer();
getCategoriesFromServer();
}, []);
return (
<StyledDashbordLayout>
<NavBar />
<SideBarDrawer />
<Grid container className="container">
{showSideBar && (
<Grid item className="sidebar-section">
<SideBar />
</Grid>
)}
<Grid item className="content">
{children}
</Grid>
</Grid>
</StyledDashbordLayout>
);
}