我现在正在做一个react 计划.我没有直接的导师,所以我不知道我的方向是否正确.

对于我的应用程序,我希望使用尽可能多的可重用组件.

目前,组件的文件夹是按类别/视图组织的

例如,我有一个按钮文件夹,它围绕着十个按钮(删除、发送、更改语言、下一步...).

here is the structure of my code at the moment :

我的标题中有多个按钮的一部分

import { Refuse } from 'components/buttons/Refuse';
import { Validate } from 'components/buttons/Validate';

export const Header = () => {

return (
<>
 <Refuse
      offerData={offerData}
      setValue={setValue}
      onSubmit={onSubmit}
      register={register}
      watch={watch}
            />
          )}{' '}
 <Validate
      register={register}
      setError={setError}
      offerData={offerData}
      setValue={setValue}
      watch={watch}
      clearErrors={clearErrors}
          />
</>
)}

然后在文件夹"components/button"中创建用于验证按钮的文件

import { Button } from '@mui/material';
import React, { useState } from 'react';
import { setActiveButton } from '../../features/buttons.slice';
import { useDispatch, useSelector } from 'react-redux';
import { AdminValidation } from '../popup/AdminValidation';

export const Validate = ({
  offerData,
  setError,
  watch,
  setValue,
  clearErrors,
  register,
}) => {
  const dispatch = useDispatch();
  const isLoading = useSelector((state) => state?.orders.loading);
  const userRole = useSelector((state) => state.user?.userGroup);
  const [ValidatePopup, setValidatePopup] = useState();

  return (
    <>
      {userRole?.includes('1') && userRole?.includes('3') ? (
        <Button
          disabled={
            offerData?.Status === 1 ||
            offerData?.Status === 3 ||
            offerData?.Status === 4
          }
          variant="contained"
          type={
            (offerData?.Paiement === 'Classique' ||
              offerData?.Paiement === 'Visa') &&
            offerData?.Status === 2
              ? 'button'
              : 'submit'
          }
          onClick={() => {
            if (
              (offerData?.Paiement === 'Classique' ||
                offerData?.Paiement === 'Visa') &&
              offerData?.Status === 2
            ) {
              setValidatePopup(true);
            } else {
              dispatch(setActiveButton('Valider'));
            }
          }}
        >
          {isLoading ? <> Chargement</> : <> Valider</>}
        </Button>
      ) : (
        <Button
          disabled={
            isLoading ||
            (userRole?.includes('1') && offerData?.Status !== 0) ||
            (userRole?.includes('2') && offerData?.Status !== 1) ||
            (userRole?.includes('3') && offerData?.Status !== 2)
          }
          variant="contained"
          type={
            (offerData?.Paiement === 'Classique' ||
              offerData?.Paiement === 'Visa') &&
            offerData?.Status === 2
              ? 'button'
              : 'submit'
          }
          onClick={() => {
            if (
              (offerData?.Paiement === 'Classique' ||
                offerData?.Paiement === 'Visa') &&
              offerData?.Status === 2
            ) {
              setValidatePopup(true);
            } else {
              dispatch(setActiveButton('Valider'));
            }
          }}
        >
          {isLoading ? <> Chargement</> : <> Valider</>}
        </Button>
      )}
      <AdminValidation
        setError={setError}
        register={register}
        setValue={setValue}
        ValidatePopup={ValidatePopup}
        setValidatePopup={setValidatePopup}
        watch={watch}
        clearErrors={clearErrors}
      />
    </>
  );
};

和一个用于拒绝按钮的文件夹

import { Button } from '@mui/material';
import React from 'react';
import { setActiveButton } from '../../features/buttons.slice';
import { useDispatch, useSelector } from 'react-redux';
import { FormDialog } from '../popup';
import { setOpen } from '../../features/popup.slice';

export const Refuse = ({ register, watch, setValue, offerData, errors }) => {
  const dispatch = useDispatch();
  const isLoading = useSelector((state) => state?.orders.loading);
  const userRole = useSelector((state) => state.user?.userGroup);

  return (
    <>
      <Button
        disabled={
          isLoading ||
          (userRole?.includes('1') &&
            userRole?.includes('3') &&
            offerData?.Status !== 0) ||
          (userRole?.includes('1') &&
            userRole?.includes('3') &&
            offerData?.Status !== 2) ||
          (userRole?.includes('1') &&
            !userRole?.includes('2') &&
            offerData?.Status !== 0) ||
          (userRole?.includes('2') &&
            !userRole?.includes('1') &&
            offerData?.Status !== 1) ||
          (userRole?.includes('3') && offerData?.Status !== 2)
        }
        variant="text"
        type="button"
        onClick={() => {
          dispatch(setOpen(true));

          dispatch(setActiveButton('Refuser'));
        }}
      >
        {' '}
        {isLoading ? <> Chargement</> : <> Refuser</>}
      </Button>{' '}
      <FormDialog
        offerData={offerData}
        register={register}
        watch={watch}
        setValue={setValue}
        errors={errors}
      />
    </>
  );
};

I was thinking of deleting all these files to create only one component, called 'button' which I would reuse for each action as below:

我的可重复使用按钮将如下所示

import { Button } from '@mui/material';

export const ButtonComponent = ({ type, style, action, texte, ...props }) => {
  return (
    <Button type={type} onClick={action} {...props}>
      {texte}
    </Button>
  );
};

我的页眉页面将调用可重用按钮

import { Refuse } from 'components/buttons/Refuse';
import { Validate } from 'components/buttons/Validate';

export const Header = () => {

return (
<>
  <> <ButtonComponent
                disabled={
                  isLoading ||
          (userRole?.includes('1') &&
            userRole?.includes('3') &&
            offerData?.Status !== 0) ||
          (userRole?.includes('1') &&
            userRole?.includes('3') &&
            offerData?.Status !== 2) ||
          (userRole?.includes('1') &&
            !userRole?.includes('2') &&
            offerData?.Status !== 0) ||
          (userRole?.includes('2') &&
            !userRole?.includes('1') &&
            offerData?.Status !== 1) ||
          (userRole?.includes('3') && offerData?.Status !== 2)
                }
                action={() => {
           dispatch(setOpen(true));

          dispatch(setActiveButton('Refuser'));}
                type={'button'}
                texte={isLoading ? langue?.loading : langue?.refused}
                variant="text"
              />
         <FormDialog
    offerData={offerData}
    register={register}
    watch={watch}
    setValue={setValue}
    errors={errors}
  /></>


          <ButtonComponent
            //same here but for validate
          />
</>
)}

问题是,调用按钮的页面最终会有更多的导入、更多的代码行.

所以我最终想知道,做这件事最好的方法是什么?

推荐答案

没有"最好"的办法.你最终会得到数以千计的答案,所有答案都描述了一种主观的方法.但我认为您需要一些帮助来构建您的组件.

您提到了您的"可重用按钮",但这是属性actiontexte的代理.其余的属性可以直接应用于<Button />.

首先,如果在渲染时返回false,Reaction组件将不会渲染.因此,你可以改变你的逻辑,转而使用早期回报.这使您的组件更具可读性.

const MyButton = () => {

   if (![statement1]) {
       return false;
   }

   if (![statement2]) {
       return false;
   }

   // if all negative statements do not match, render it
   return (
      <button />
   )
}

第二个提示是,不要在组件中混合业务逻辑.创建存储业务逻辑的单独文件.

# offer_logic.js

export canRefuse = (offer) => {
   // your business logic here to determine if an offer can be refused
   return [your_logic];
}

然后,您可以在您的组件中使用它. Select 哪个组件(按钮或呈现按钮的位置)由您决定.

import OfferLogic from 'offer_logic';

// ... 


{OfferLogic.canRefuse(offer) && (
    <Button onClick={..}>Refuse offer</Button>
)}

// or 

const RefuseButton = (offer) => {
   if (!OfferLogic.canRefuse(offer)) {
       return false;
   }
   return (
      <Button onClick={..}>Refuse offer</Button>
   );
}

如果你的offer是一个模型,你可以将逻辑添加到你的模型中.

这应该可以防止您构建复杂的组件,并减少由于重复而导致的代码抽象.它还应该使您的组件更具可读性和可测试性.

最后一个建议是,可以使用更多的逻辑来增强您的API(或其他数据源)将生成的数据.例如,让你的后台决定是否可以拒绝一项提议,这样你的应用程序就不必决定这一点.有很多方法可以用于您的后端,但我不会在这里讨论,因为这不是您的问题.

Javascript相关问答推荐

Next.js Next/Image图像隐含性有任何类型-如何修复?

RxJS setTimeout操作符等效

我开始使用/url?q=使用Cheerio

我应该绑定不影响状态的函数吗?'

仅针对RTK查询中的未经授权的错误取消maxRetries

当作为表达式调用时,如何解析方法decorator 的签名?

JS—删除对象数组中对象的子对象

使用ThreeJ渲染的形状具有抖动/模糊的边缘

如何修复我的数据表,以使stateSave正常工作?

将异步回调转换为异步生成器模式

为什么在函数中添加粒子的速率大于删除粒子的速率?

如何找到带有特定文本和测试ID的div?

如何组合Multer上传?

无法向甜甜圈图表上的ChartJSImage添加可见标签

将字符串解释为数字;将其重新编码为另一个基数

如何使用useparams从react路由中提取id

在Reaction Native中,ScrolltoIndex在结束时不一致地返回到索引0

使用JavaScript或PHP从div ID值创建锚标记和链接

响应,Use Callback更新状态变量,该变量也存在于其依赖数组中,它如何防止无限重新呈现?

元素类型无效:应为字符串(对于内置组件)或类/函数(对于复合组件),但GET:Object.在Reaction项目中