Skip to content

Commit

Permalink
fix(withalien): return component when ReduxModule is resolve
Browse files Browse the repository at this point in the history
use withAlien on routing to assure component's data ahead

#43
  • Loading branch information
aneurysmjs committed Dec 31, 2019
1 parent e44b566 commit 10533a2
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 40 deletions.
42 changes: 13 additions & 29 deletions src/app/components/pages/Home/Home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,46 +2,30 @@
import React, { useEffect, ReactElement } from 'react';
import { useDispatch, useSelector } from 'react-redux';

import { useAlien } from '~/store/config/alienStore';
import { AlienResult } from '~/store/config/alienStore/useAlien';

// import Spinner from '~/components/base/Spinner';
// import ProductCard from '~/components/common/ProductCard';
//
// import { fetchProducts } from '~/store/modules/products/actions';
// import { getProducts } from '~/store/modules/products/selectors';
//
// import { ProductsStateType } from '~/store/modules/products/types';
import Spinner from '~/components/base/Spinner';
import ProductCard from '~/components/common/ProductCard';

import { ProductsStateType } from '~/store/modules/products/types';

import './Home.scss';

const Home = (): ReactElement => {
const dispatch = useDispatch();
// const { isLoading, products, error }: ProductsStateType = useSelector(getProducts);
type PropsType = AlienResult;

// useEffect(() => {
// dispatch(fetchProducts(`/products`));
// }, [dispatch]);
const result = useAlien({
getModule: () => import('~/store/modules/products'),
});
const Home = (props: PropsType): ReactElement => {
const dispatch = useDispatch();
const { isLoading, products, error }: ProductsStateType = useSelector(props.selectors.getProducts);

// const selector = result ? result.selectors.getProducts : (): {} => ({});

// const { isLoading, products, error } = useSelector(selector);

useEffect(() => {
if (result) {
dispatch(result.actions.fetchProducts(`/products`));
}
}, [dispatch, result]);

console.log('result', result);
dispatch(props.actions.fetchProducts(`/products`));
}, [dispatch, props.actions]);

return (
<div className="home">
<h2 className="home__title">Shop</h2>
<div className="row">
{/* {error ? <span className="home__loader">{error.message}</span> : null}
{error ? <span className="home__loader">{error.message}</span> : null}
{isLoading ? (
<span className="home__loader">
<Spinner />
Expand All @@ -58,7 +42,7 @@ const Home = (): ReactElement => {
<ProductCard width="100%" product={product} />
</div>
))
: null} */}
: null}
</div>
</div>
);
Expand Down
8 changes: 7 additions & 1 deletion src/app/components/routing/Routing.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
/* eslint-disable @typescript-eslint/explicit-function-return-type */
import React, { ReactElement } from 'react';
import { Route } from 'react-router-dom';

import Layout from '~/components/core/Layout';
import withAlien from '~/store/config/alienStore/withAlien';

import Home from '~/components/pages/Home';

const Routing = (): ReactElement => (
<main>
<Layout>
<Route exact path="/" component={Home} />
<Route
exact
path="/"
component={() => withAlien(Home, () => import('~/store/modules/products'))}
/>
</Layout>
</main>
);
Expand Down
7 changes: 5 additions & 2 deletions src/app/store/config/alienStore/useAlien.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ export interface ReduxModule<T = {}> {
actions: {
[K: string]: ActionCreator<AnyAction>;
};
selectors?: {
[K: string]: <S>(state: S) => T;
};
}

export type AlienResult = Omit<ReduxModule, 'reducers'>;
Expand Down Expand Up @@ -41,14 +44,14 @@ function useAlien<T>(alienModule: AlienModule<T>): AlienResult | null {
useEffect(() => {
(async (): Promise<void> => {
try {
const { reducers, actions } = await alienModule.getModule();
const { reducers, actions, selectors } = await alienModule.getModule();
const key = Object.keys(reducers).shift();

if (key) {
injectReducers(key, reducers[key]);
store.replaceReducer(rootReducer);
}
setAlien({ actions });
setAlien({ actions, selectors });
} catch (err) {
setAlien(err);
}
Expand Down
6 changes: 2 additions & 4 deletions src/app/store/config/alienStore/withAlien.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { ReactElement, ReactNode, ComponentType } from 'react';
import React, { ReactElement, ReactNode, FunctionComponent } from 'react';
import { Store, AnyAction } from 'redux';
import { Provider } from 'react-redux';
import { renderHook } from '@testing-library/react-hooks';
Expand All @@ -18,7 +18,7 @@ type WrapperProps = {
};

// eslint-disable-next-line react/prop-types
const wrapper: ComponentType<WrapperProps> = ({ children }) => (
const wrapper: FunctionComponent<WrapperProps> = ({ children }) => (
<Provider store={store}>{children}</Provider>
);

Expand Down Expand Up @@ -54,8 +54,6 @@ describe('test "withAlien"', () => {
wrapper,
});

expect(result.current.props).toStrictEqual({});

await waitForNextUpdate();

expect(result.current.props.actions).toStrictEqual(reduxModule.actions);
Expand Down
15 changes: 11 additions & 4 deletions src/app/store/config/alienStore/withAlien.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import React, { ReactElement, ComponentType } from 'react';
import React, { ReactElement, ComponentType, ReactNode } from 'react';

import useAlien, { ReduxModule, AlienResult } from './useAlien';

interface WithAlienProps {
children?: ReactNode;
actions: AlienResult['actions'];
}

function withAlien<P extends object>(
function WithAlien<P extends object>(
Component: ComponentType<P>,
getModule: () => Promise<ReduxModule>,
): ReactElement<P & WithAlienProps> | null {
Expand All @@ -17,7 +18,13 @@ function withAlien<P extends object>(
getModule,
});

return <Component {...((alienResult && alienResult) as P)} />;
if (alienResult) {
return <Component {...(alienResult as P)} />;
}

return null;
// return <Component {...((alienResult && alienResult) as P)} />;
// return typeof props.children === 'function' ? props.children() : props.children;
}

export default withAlien;
export default WithAlien;

0 comments on commit 10533a2

Please sign in to comment.