不确定我是否正确编写了高阶组件

Unsure if I'm writing my higher order components correctly

在我正在开发的 React 应用程序中,我将各种组件包装在我编写的 HOC 中,以执行检查身份验证等操作。我想知道我这样做的方式是好是坏。 HOC 的工作正如预期的那样,但我想知道我是否在做一些不太好的事情。这是一个例子: 如果用户转到 /profile,将呈现组件 ProfilePage.js

import React from 'react';
import Profile from './Profile';
import withLogin from './hoc/withLogin';
import { connect } from 'react-redux';

export const ProfilePage = props => <div> <Profile /> </div>

const mapStateToProps = ({ auth }) => ({ auth });
export default connect(mapStateToProps)(withLogin(ProfilePage));

这是Profile.js:

import React from 'react';
import { connect } from 'react-redux';
import ProfileForm from './ProfileForm';
export const Profile = props => {
    const render = () => {
        return (
            <div>
                <h1>Profile component</h1>
                <ProfileForm />
            </div>
        );
    };
    return <div>{render()}</div>;
};

const mapStateToProps = ({ auth }) => ({ auth });

export default connect(mapStateToProps)(Profile);

这是我的 withLogin.js 文件:

import React from 'react';
import RequireLogin from './RequireLogin';

export default () => Component => <RequireLogin component={Component} />;

,这里是 RequireLogin.js

import React from 'react';
import { connect } from 'react-redux';
import Loading from '../Loading';
import { Redirect } from 'react-router-dom';

export const RequireLogin = ({ component: Component, ...rest }) => {
    switch (rest.auth) {
        case null:
            return <Loading />;
        case false:
            return <Redirect to='/' />;
        default:
            return <Component />;
    }
};
const mapStateToProps = ({ auth }) => ({ auth });
export default connect(mapStateToProps)(RequireLogin);

编辑:看来我没有花足够的时间研究这个测试问题。我的 withLogin 函数 returns 是一个组件,所以我需要在测试用例中浅渲染它。像这样:

import React from 'react';
import { shallow } from 'enzyme';
import withLogin from '../withLogin';

test('withLogin renders RequireLogin', () => {
    const MyComponent = () => <div>myComponent</div>;
    const Wrapped = withLogin(MyComponent);
    const wrapper = shallow(<Wrapped />);
    expect(wrapper).toMatchSnapshot();
});

这张快照returns符合我的预期。 不过,我仍然对有关高阶组件的最佳实践有疑问。

我确实担心这个问题现在可能有点太长了,但是如果我确实对我的 HOC 做错了什么,我可能会遇到另一个问题:我很难用 Jest 测试它们。 我的 withLogin.js 文件的测试文件如下所示:

import React from 'react';
import { shallow } from 'enzyme';
import withLogin from '../withLogin';

test('withLogin renders RequireLogin', () => {
    const myComponent = () => <div>Component</div>;
    const wrapper = withLogin(myComponent);
    expect(wrapper).toMatchSnapshot();
});

但只有快照 returns 这个:

// Jest Snapshot v1

exports[`withLogin renders RequireLogin 1`] = `[Function]`; //Here i would expect to see an instance of <RequireLogin />

我的 RequireLogin.js 测试文件如下所示:

import React from 'react';
import { shallow } from 'enzyme';
import { RequireLogin } from '../RequireLogin';
import users from '../../../fixtures/users';
test('RequireLogin renders <Loading /> if auth is null', () => {
    const wrappedComponent = <div>wrappedComponent</div>;
    const wrapper = shallow(<RequireLogin auth={null} component={wrappedComponent} />);
    expect(wrapper).toMatchSnapshot();
});

test('RequireLogin renders <Redirect to="/profile" /> if auth is false', () => {
    const wrappedComponent = <div>wrappedComponent</div>;
    const wrapper = shallow(<RequireLogin auth={false} component={wrappedComponent} />);
    expect(wrapper).toMatchSnapshot();
});

test('RequireLogin renders <Component /> if auth is valid', () => {
    const wrappedComponent = <div>wrappedComponent</div>;
    const wrapper = shallow(<RequireLogin auth={users[0]} component={wrappedComponent} />);
    expect(wrapper).toMatchSnapshot();
});

但是快照 returns 这个:

// Jest Snapshot v1

exports[`RequireLogin renders <Component /> if auth is valid 1`] = `<[object Object] />`; //Here i would expect <Component />

exports[`RequireLogin renders <Loading /> if auth is null 1`] = `<Loading />`;

exports[`RequireLogin renders <Redirect to="/profile" /> if auth is false 1`] = `
<Redirect
  push={false}
  to="/"
/>
`;

我所有其他组件的所有快照测试都按预期工作。我怀疑它可能与连接到我的 Redux 商店的 RequireLogin 组件有关,但我没有在测试文件中模拟商店?在此先感谢您的帮助!

我建议您将看起来不错的 HOC 转为渲染道具。 这样做有很多好处。示例:由于 render props Composition patten 在 运行 时组合,您不必担心名称 space 与在编译时组合的 HOC 冲突。 还有其他好处,请阅读下文 阅读:https://reactrocket.com/post/turn-your-hocs-into-render-prop-components/ 要么 阅读:https://cdb.reacttraining.com/use-a-render-prop-50de598f11ce 找出 HOC 的其他好处