J'ai une situation délicate et je suis incapable de la contourner et d'apporter une solution de contournement. Tout conseil technique est apprécié.

Voici un exemple.

J'ai un tableau et j'affiche quelques tâches dans chaque ligne. Certaines lignes peuvent avoir des sous-tâches supplémentaires. Il y a une dernière colonne sur le tableau avec des icônes pour développer et réduire pour les sous-tâches,

Lorsque l'utilisateur active le bouton fléché de la sous-tâche, il développe ou réduit cette sous-tâche. Ainsi, l'utilisateur peut cliquer individuellement sur la flèche pour chaque ligne de sous-tâche et les sous-tâches ci-dessous s'afficheront ou se cacheront en fonction de la bascule. J'espère qu'il est logique d'expliquer cela.

Maintenant, je veux utiliser une icône développer / réduire au niveau de l'en-tête. Si l'utilisateur bascule à l'aide de l'icône au niveau de l'en-tête, toutes les sous-tâches sont réduites / développées en même temps.

Comment puis-je m'assurer qu'un utilisateur peut développer / réduire au niveau de l'en-tête et également au niveau des sous-tâches en même temps. Parce que dans ma situation, si je réduis le niveau d'en-tête, je ne peux pas développer le niveau de sous-tâche individuellement car il a un indicateur qui pointe vers l'icône de niveau d'en-tête.

C'est-à-dire que si headerIcon est false, le niveau de sous-tâche est également défini sur false. Maintenant, lorsque le niveau de la sous-tâche est faux, si j'essaie de cliquer sur le niveau de la sous-tâche et de développer cette sous-tâche particulière, cela ne me permettra pas car le headerIcon est toujours faux.

Comment puis-je m'assurer que je peux développer / réduire à la fois au niveau de l'en-tête et au niveau de la sous-tâche. S'il vous plaît laissez-moi savoir si ce n'est pas clair, je vais essayer de le rendre plus clair en éditant cette question.

0
ashwin prabhu 19 oct. 2020 à 07:15

2 réponses

Meilleure réponse

TLDR: ayez une classe à bascule CSS sur SubTask et transmettez l'état TaskItem parent à la sous-tâche, useEffect pour mettre à jour l'état de l'enfant avec les mises à jour des parents.

Live Cond Sandbox ici

Panne...


Voici une autre approche. J'aime séparer l'état des données. Tout comme la réaction est rapide avec sa réconciliation, je préfère mettre à jour la structure DOM pour les mises à jour qui ne touchent que la mise en page , via CSS. De cette façon, je peux utiliser une classe supplémentaire sur l'élément conteneur qui masque et montre les enfants au lieu de re-rendre l'arborescence entière de manière conditionnelle. Plus encore si les mises à jour ne touchent pas la logique de données sous-jacente, j'opte pour le contrôle css dans ce cas.

Sur la base de votre déclaration / question, How can I ensure that a user can expand/collapse at header level and also at subtasks level at the same time., j'ai supposé que pour que cela soit réalisable, vous ne pouvez jamais réduire complètement la tâche sans afficher une liste des sous-tâches, j'ai structuré la mise en page de la tâche approchée.

Supposons la structure arborescente des composants suivante

Tasks (ul.tasks-list)
│
└───header (li.heading)
│
└───TaskItem 1 (li.task) // -> .task-collapsed
│ └───task-summary (div.task-main)
│ │ │ - Title
│ │ │ - Assignee
│ │ └ - Expand Icon Action (onClick parent)
│ │
│ └───SubTasks (ul.subtasks-list)
│ └─── SubTaskItem 1 (li.subtask) // -> .subtask-collapsed
│ └───subtask-summary (div.subtask-summary)
│ │ │ - Title
│ │ │ - Summary
│ │ └ - Expand Icon Action (onClick subtask)
│ │
│ └───subtask-body (div.subtask-body) // Targeted by CSS.
  1. Cela dit, demandez aux sous-tâches individuelles de contrôler leur propre état de visibilité en basculant une classe (.subtask-collapsed) sur leur conteneur (.subtask) en cliquant sur la flèche vers le bas. Ayez un style CSS qui cible le subtask body et cache les détails. Définissez l'état initial à partir de l'état collapsed parent.
&.subtask {
  &.subtask-collapsed {
    .subtask-summary {
      .arrow-icon {
        transform: rotate(0deg);
        transition: transform 0.2s ease-out;
      }
    }

    .subtask-body {
      display: none;
    }
  }
}
  1. Étant donné que le parent a le contrôle sur plusieurs enfants et a le pouvoir de remplacer l'état des enfants, demandez aux enfants de garder un œil sur l'état du parent. Si l'état du parent change, forcez également les enfants à se mettre à jour.

const SubTaskItem = ({
  title,
  summary,
  status,
  descripiton,
  parentExpanded
}) => {
  const [isExpanded, setIsExpanded] = useState(parentExpanded);

  const handleClick = () => {
    setIsExpanded(() => !isExpanded);
  };

  // Note :: This is important to force re-rendering of child when parent updates prop.
  useEffect(() => {
    setIsExpanded(() => parentExpanded);
  }, [parentExpanded]);

  return (
    <li className={`subtask ${!isExpanded ? "subtask-collapsed" : ""}`}>
      <div className="subtask-summary">
        <div className="col">{title}</div>
        <div className="col">{summary}</div>
        <div className="col" onClick={handleClick}>
          <Arrow />
        </div>
      </div>
      <div className="subtask-body">
        <h3>Title: {title}</h3>
        <h4>Summary: {summary}</h4>
        <h4>Status: {status}</h4>
        <p>{descripiton}</p>
      </div>
    </li>
  );
};
  1. Nous pourrions contrôler les classes CSS parentes et faire en sorte que les sous-classes de tâches des enfants aient leurs styles remplacés par important, mais cela devient très vite moche. Au lieu de cela, dans ce cas, nous transmettons l'état parent comme accessoire.

const TaskItem = ({ title, assigned, subTasks }) => {
  const [isExpanded, setIsExpanded] = useState(false);

  const handleClick = () => {
    setIsExpanded(() => !isExpanded);
  };

  return (
    <li className={`task ${!isExpanded ? "task-collapsed" : ""}`}>
      <div className="task-main">
        <div className="col">{title}</div>
        <div className="col">{assigned}</div>
        <div className="col task-action" onClick={handleClick}>
          <Arrow />
        </div>
      </div>
      {/* Parent Task passes down status to force subtasks to update */}
      <SubTasks parentExpanded={isExpanded} subtaskItems={subTasks} />
    </li>
  );
};

Remarque:

  • Parfois, les mises à jour de l'accessoire ne forcent pas les enfants à effectuer un nouveau rendu. Avoir un hook useEffect qui force l'enfant à recalculer son état si l'état parent parentExpanded change.
  • PS, en ce qui concerne l'expérience utilisateur, j'espère que vous avez un bouton d'action qui réduit complètement les sous-tâches afin que vous ne puissiez voir qu'une liste de tâches minimale

Voici le lien vers le CodeSandbox qui a la démo fonctionnelle.

1
iamcastelli 19 oct. 2020 à 09:46

Il y a plusieurs façons de le faire, mais je le ferais de la manière suivante. Tout d'abord, définissons votre structure de données. Disons que c'est un tableau d'objets de tâche. Chaque objet a une propriété name de votre tâche et un tableau d'objets de sous-tâche subtasks. Chaque objet de sous-tâche contient un nom de la sous-tâche et une propriété hidden, quand c'est vrai, la sous-tâche est visible et quand elle est fausse, elle est cachée / réduite.

Pour illustrer:

  state = {
    tasks: [{
        name: "Task 1",
        subtasks: [{
          name: "Subtask 1A",
          hidden: false
        }, {
          name: "Subtask 1B",
          hidden: false
        }]
      },
      {
        name: "Task 2",
        subtasks: [{
          name: "Subtask 2A",
          hidden: false
        }, {
          name: "Subtask 2B",
          hidden: false
        }]
      }
    ]
  };

Notez que nous n'avons pas la propriété de niveau d'en-tête hidden ni aucun 'indicateur' de quelque sorte que ce soit qui indique qu'un en-tête est réduit ou non. C'est juste plus facile de gérer l'état sans cela.

Alors, comment faites-vous alors?

  1. Pour réduire ou afficher une sous-tâche, vous modifiez la valeur de hidden en vrai ou faux.
  2. Pour réduire ou afficher toutes les sous-tâches d'une tâche, vous parcourez toutes ses sous-tâches enfants et modifiez leurs propriétés hidden en true ou false.

En d'autres termes, vous conservez l'état d'une tâche dans ses sous-tâches, vous avez donc 3 états qui ne sont pas directement définis sur une tâche mais dépendent de l'état de ses sous-tâches:

  1. Toutes les propriétés hidden des sous-tâches sont true signifie que l'ensemble la tâche est réduite
  2. Toutes les propriétés hidden des sous-tâches sont false signifie que toute la tâche est affichée
  3. Si certaines des sous-tâches sont masquées et d'autres non, vous êtes dans un état mixte.

De la même manière, vous pouvez implémenter un bouton pour réduire / afficher toutes les sous-tâches de toutes les tâches, mais la fonction derrière cela au lieu de changer le statut de toutes les sous-tâches d'une tâche particulière, vous parcourez toutes les sous-tâches de toutes les tâches.

1
IvanD 19 oct. 2020 à 05:34