在我正在研究的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
组件有关,但我没有在测试文件中模拟商店?在此先感谢您的帮助!
答案 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的其他好处