reactjs - 如何使用 reactjs redux-saga 将数组渲染到列表
问题描述
您好这几天我正在尝试使用 redux-saga 呈现产品列表。我使用 react-boilerplate 作为我的结构。我有两个组件 ProductsList 和 ProductsItem:
ProductsList.js
function ProductsList({ loading, error, products }) {
if (loading) {
return <List component={LoadingIndicator} />;
}
if (error !== false) {
const ErrorComponent = () => (
<ListItem item="Something went wrong, please try again!" />
);
return <List component={ErrorComponent} />;
}
if (products !== false) {
return <List items={products} component={Products} />;
}
return null;
}
ProductsList.propTypes = {
loading: PropTypes.bool,
error: PropTypes.any,
products: PropTypes.any,
};
export default ProductsList;
产品.js:
function Products(props) {
return (
<div className="contact">
<span>{props.title}</span>
</div>
);
}
Products.propTypes = {
title: PropTypes.string.isRequired
};
List.js
function List(props) {
const ComponentToRender = props.component;
let content = <div />;
// If we have items, render them
if (props.items) {
content = props.items.map(item => (
<ComponentToRender key={`item-${item.id}`} item={item} />
));
} else {
// Otherwise render a single component
content = <ComponentToRender />;
}
return (
<Wrapper>
<Ul>{content}</Ul>
</Wrapper>
);
}
List.propTypes = {
component: PropTypes.func.isRequired,
items: PropTypes.array,
};
我的主页容器使用 ComponentDidMount 函数调用一个操作(Everyting 在那里工作,我对其进行了调试)。但也许原型 ant 渲染有问题。
MainPage.js
class MainPage extends React.Component {
componentDidMount() {
this.props.onFetch();
}
render() {
const { error, loading, products } = this.props;
const reposListProps = {
loading,
error,
products,
};
return (
<article>
<Helmet>
<title>Products</title>
<meta
name="description"
content="A React.js Boilerplate application products"
/>
</Helmet>
<div>
<ProductsList {...reposListProps} />
</div>
</article>
);
}
}
PostedCasesClient.propTypes = {
loading: PropTypes.bool,
error: PropTypes.oneOfType([PropTypes.object, PropTypes.bool]),
products: PropTypes.oneOfType([PropTypes.array, PropTypes.bool]),
onFetch: PropTypes.func
};
export function mapDispatchToProps(dispatch) {
return {
onFetch: evt => {
dispatch(fetchProducts());
},
};
}
const mapStateToProps = createStructuredSelector({
mainPage: makeSelectPostedCasesClient
});
const withConnect = connect(
mapStateToProps,
mapDispatchToProps,
);
const withReducer = injectReducer({ key: 'main', reducer }); const withSaga = injectSaga({ key: 'main', saga });
导出默认 compose( withReducer, withSaga, withConnect, )(MainPage);
稍后在发送我的 fetchProduct 操作后,我使用 sagas。这部分也有效,因为我将我的产品数组放入减速器。
Saga.js
export function* getProducts() {
try {
let requestURL = 'http://localhost:8080/produts';
const products = yield call(request, requestURL, { method: 'GET' });
yield put(fetchProductSuccess(products));
} catch (error) {
yield put(type: 'FETCH_PRODUCTS_FAILURE', error)
console.log(error);
}
}
export default function* actionWatcher() {
yield takeLatest(FETCH_PRODUCTS_BEGIN, getProducts)
}
减速器.js
const initialState = fromJS({
loading: false,
error: false,
items: false
});
function ProductsReducer(state = initialState, action) {
switch(action.type) {
case FETCH_PRODUCTS_BEGIN:
return state
.set('loading', true)
.set('error', false)
.setIn('items', false);
case FETCH_PRODUCTS_SUCCESS:
return state
.setIn('items', action.products)
.set('loading', false)
case FETCH_PRODUCTS_FAILURE:
return state.set('error', action.error).set('loading', false);
default:
return state;
}
}
也许有人可以告诉我我做错了什么?如果您需要更多代码,请告诉我,我将对其进行编辑。
编辑:
这是我的选择器:
const selectGlobal = state => state.get('global');
const makeSelectMainClient = () =>
createSelector(selectMainPageDomain, substate => substate.toJS());
const makeSelectLoading = () =>
createSelector(selectGlobal, globalState => globalState.get('loading'));
const makeSelectError = () =>
createSelector(selectGlobal, globalState => globalState.get('error'));
const makeSelectProducts = () =>
createSelector(selectGlobal, globalState =>
globalState.getIn(['products']),
);
export default makeSelectPostedCasesClient;
export {
selectMainPageDomain,
selectGlobal,
makeSelectLoading,
makeSelectError,
makeSelectProducts,
};
解决方案
您需要更新mapStateToProps
连接MainPage
组件的函数以接收新减速器中的数据。目前您有:
const mapStateToProps = createStructuredSelector({
mainPage: makeSelectPostedCasesClient
});
但是,您的组件期望接收loading
、error
和products
。您将需要创建一个mapStateToProps
将这些变量提供给组件的函数。就像是:
const mapStateToProps = createStructuredSelector({
products: makeSelectProducts(),
loading: makeSelectLoading(),
error: makeSelectError(),
});
您可能必须编写自己的选择器才能从ProductsReducer
. 一旦你这样做了,当你的 reducer 获取新数据时,选择器将自动获取新数据并更新你的组件。
推荐阅读
- php - 将 Cloudinary 与 spatie/media-library Laravel 包一起使用
- node.js - Node/Express:使用 SuperAgent 从 URL 读取 JSON 文件
- python - Django - 模板渲染性能(我认为)如何检查启用 LocMemCache 是否有效?
- python - Python rsa 模块的麻烦
- business-intelligence - Cognos Analytics,交叉表中有多个列,但度量中只有一行
- django - Django,如何从 s3 迁移到 CDN?
- java - 子类测试中的 JUnit4 NullPointerException,覆盖方法
- javascript - 如何执行我的代码以获得想要的结果
- vue.js - Vuelidate 在点击操作时验证 bootstrapvue / vue 表单字段
- azure - 更新 Azure 机器人中的默认名称