调用这个反应 HOC 感觉我可以用另一种方式抽象它请建议

Calling this react HOC feels like i could abstract this in another way please advice

我是初学者,需要建议。我学习了 Reactjs 并创建了这个 HOC,这样我就可以在 Router V6 中导航。我担心的是,从我的桌面 Navbar 和移动侧菜单我有指向相同 Dashboard.

的链接

所以我创建了一个 HOC,因为它在两个位置都是相同的代码 运行,并且 HOC 现在有这个代码。

这是 HOC:

import React from 'react';
import AuthUserContext from './context';
import * as ROLES from '../constants/roles';

const WithDashboardNavigate = Component => {
    class WithDashboardBase extends React.Component {
        constructor() {
            super();
            this.onDashboard = this.onDashboard.bind(this);
        }

        onDashboard = navigate => {
            const { authUser } = this.props;
            if (authUser) {
                if (authUser.roles.includes(ROLES.ANON)) {
                    navigate('/app/login');
                } else if (authUser.roles.includes(ROLES.USER) || authUser.roles.includes(ROLES.ADMIN)) {
                    const view = localStorage.getItem('currentDashBoardView');
                    // Here if user has used nav menu earlier then that last view is loaded
                    if (view) navigate(view);
                    // or default to dash
                    else navigate('/app/dashboard');
                }
            }
        };

        render() {
            return <Component dashboardNavigater={this.onDashboard} {...this.props} />;
        }
    }

    const WithDashboard = () => (
        <AuthUserContext.Consumer>
            {authUser => (
                <div>
                    <WithDashboardBase authUser={authUser} />
                </div>
            )}
        </AuthUserContext.Consumer>
    );

    return WithDashboard;
};

export default WithDashboardNavigate;

我从 Navbar 中这样使用它:

function SignedInButton(props) {
    const navigate = useNavigate();

    function openDashboard() {
        props.dashboardNavigater(navigate);
    }

    return (
        <div>
            <Button className="button is-large" onClick={openDashboard}>
                <span className="icon is-medium">
                    <i className="fas fa-user" />
                </span>
            </Button>
        </div>
    );
}

export default WithDashboardNavigate(SignedInButton);

我从 SideMenu 中这样使用它:

/* eslint-disable jsx-a11y/anchor-is-valid */
import React from 'react';
import { useNavigate } from 'react-router-dom';
import styled from 'styled-components';
import WithDashboardNavigate from '../../session/WithDashboardNavigate';

function SideMenu(props) {
    const { close, dashboardNavigater } = props;
    const navigate = useNavigate();

    const onProfilePageClick = () => {
        if (close) close();
        dashboardNavigater(navigate);
    };

    return (
        <div>
            <MenuLinksSpace />
            <MenuLinks>
                <li>
                    <a onClick={onProfilePageClick} role="presentation">
                        <span className="icon is-medium">
                            <i className="fas fa-user" />
                        </span>{' '}
                        Dashboard
                    </a>
                </li>
            </MenuLinks>
        </div>
    );
}

我的问题是我做得太过分了吗?我的意思是有没有更简单的方法来更好地符合 React 最佳实践?

这完全取决于需求和您的设计方式。我的观点是,如果您使用功能组件,则不需要与 class 组件和 bind(this).

混合使用

注意: 如果任何组件传递未传递给 WithDashboardBase 的道具,则您不会通过 WithDashboard 函数传递道具。

import React from 'react';
import AuthUserContext from './context';
import * as ROLES from '../constants/roles';

const WithDashboardNavigate = Component => {
    const WithDashboardBase = (props) => {
       const onDashboard = navigate => {
            const { authUser } = props;
            if (authUser) {
                if (authUser.roles.includes(ROLES.ANON)) {
                    navigate('/app/login');
                } else if (authUser.roles.includes(ROLES.USER) || authUser.roles.includes(ROLES.ADMIN)) {
                    const view = localStorage.getItem('currentDashBoardView');
                    // Here if user has used nav menu earlier then that last view is loaded
                    if (view) navigate(view);
                    // or default to dash
                    else navigate('/app/dashboard');
                }
            }
        };

        return <Component dashboardNavigater={onDashboard} {...props} />;
    }

    const WithDashboard = (props) => (   // Pass props from here as well 
        <AuthUserContext.Consumer>
            {authUser => (
                <div>
                    <WithDashboardBase authUser={authUser} {...props} />
                </div>
            )}
        </AuthUserContext.Consumer>
    );

    return WithDashboard;
};

export default WithDashboardNavigate;

我已经为上下文API创建了连接 HOC(与 redux 相同)。检查这个它会帮助你理解从 parent 到 child 的道具传递。

https://stackblitz.com/edit/reactjs-usecontext-usereducer-state-management?file=src%2FStore.js