import { useEffect } from 'react'; import { bindActionCreators } from 'redux'; import { connect } from 'react-redux'; import PropTypes from 'prop-types'; import Loader from '../loader'; import Error from '../error'; import { fetchData } from '../../utils/fetch'; import { ERROR, INIT, LOADING } from '../../../redux/constants'; function Fetcher(props) { useEffect(() => fetchData(props.action), [props.action]); // Loading if ([INIT, LOADING].includes(props.status)) return ; // Error if (props.status === ERROR) { const result = props.renderError(props.error); if (result !== null) return result; } // Empty Data if ( (Array.isArray(props.data) && props.data.length === 0) || (Object.entries(props.data).length === 0 && props.data.constructor === Object) ) { const result = props.renderEmpty(); if (result !== null) return result; } // Good Condition return props.children(props.data); } Fetcher.propTypes = { action: PropTypes.func.isRequired, stateSelector: PropTypes.func.isRequired, status: PropTypes.string.isRequired, data: PropTypes.oneOfType([PropTypes.object, PropTypes.arrayOf(PropTypes.object)]).isRequired, renderEmpty: PropTypes.func.isRequired, renderError: PropTypes.func.isRequired }; Fetcher.defaultProps = { renderEmpty: () => null, renderError: () => }; function mapStateToProps(state, { stateSelector }) { return { status: stateSelector(state).status, error: stateSelector(state).error, data: stateSelector(state).data }; } function mapDispatchToProps(dispatch, { action }) { return bindActionCreators({ action }, dispatch); } export default connect(mapStateToProps, mapDispatchToProps)(Fetcher);