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

时间:2018-03-08 17:26:41

标签: reactjs unit-testing jestjs higher-order-functions higher-order-components

在我正在研究的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函数返回一个组件,所以我需要在测试用例中浅显示它。像这样:

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();
});

此快照返回我的预期。 我仍然对有关高阶组件的最佳实践有疑问。

我担心这个问题现在可能会变得有点太长,但是如果我确实对我的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();
});

但快照只返回:

// 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();
});

但快照会返回:

// 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组件有关,但我没有在测试文件中模拟商店?在此先感谢您的帮助!

1 个答案:

答案 0 :(得分:1)

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