ソースを参照

[FE] Use id field for keys

Azat Mutigullin 4 年 前
コミット
be4b9543ce

+ 12 - 4
kafka-ui-react-app/src/components/Dashboard/ClustersWidget/ClustersWidget.tsx

@@ -12,6 +12,11 @@ interface Props {
   offlineClusters: Cluster[];
 }
 
+interface ChunkItem {
+  id: string;
+  data: Cluster[];
+}
+
 const ClustersWidget: React.FC<Props> = ({
   clusters,
   onlineClusters,
@@ -19,14 +24,17 @@ const ClustersWidget: React.FC<Props> = ({
 }) => {
   const [showOfflineOnly, setShowOfflineOnly] = React.useState<boolean>(false);
 
-  const clusterList: Array<Cluster[]> = React.useMemo(() => {
+  const clusterList: ChunkItem[] = React.useMemo(() => {
     let list = clusters;
 
     if (showOfflineOnly) {
       list = offlineClusters;
     }
 
-    return chunk(list, 2);
+    return chunk(list, 2).map((data) => ({
+      id: v4(),
+      data,
+    }));
   }, [clusters, offlineClusters, showOfflineOnly]);
 
   const handleSwitch = () => setShowOfflineOnly(!showOfflineOnly);
@@ -56,8 +64,8 @@ const ClustersWidget: React.FC<Props> = ({
       </MetricsWrapper>
 
       {clusterList.map((chunkItem) => (
-        <div className="columns" key={v4()}>
-          {chunkItem.map((cluster) => (
+        <div className="columns" key={chunkItem.id}>
+          {chunkItem.data.map((cluster) => (
             <ClusterWidget cluster={cluster} key={cluster.id} />
           ))}
         </div>

+ 1 - 2
kafka-ui-react-app/src/components/Topics/Details/Settings/Settings.tsx

@@ -1,5 +1,4 @@
 import React from 'react';
-import { v4 } from 'uuid';
 import { ClusterName, TopicName, TopicConfig } from 'redux/interfaces';
 
 interface Props {
@@ -57,7 +56,7 @@ const Sertings: React.FC<Props> = ({
         </thead>
         <tbody>
           {config.map((item) => (
-            <ConfigListItem key={v4()} config={item} />
+            <ConfigListItem key={item.id} config={item} />
           ))}
         </tbody>
       </table>

+ 1 - 2
kafka-ui-react-app/src/components/Topics/List/List.tsx

@@ -1,5 +1,4 @@
 import React from 'react';
-import { v4 } from 'uuid';
 import { TopicWithDetailedInfo, ClusterName } from 'redux/interfaces';
 import Breadcrumb from 'components/common/Breadcrumb/Breadcrumb';
 import { NavLink } from 'react-router-dom';
@@ -60,7 +59,7 @@ const List: React.FC<Props> = ({ clusterName, topics, externalTopics }) => {
           </thead>
           <tbody>
             {items.map((topic) => (
-              <ListItem key={v4()} topic={topic} />
+              <ListItem key={topic.id} topic={topic} />
             ))}
           </tbody>
         </table>

+ 1 - 2
kafka-ui-react-app/src/components/common/Breadcrumb/Breadcrumb.tsx

@@ -1,6 +1,5 @@
 import React from 'react';
 import { NavLink } from 'react-router-dom';
-import { v4 } from 'uuid';
 
 interface Link {
   label: string;
@@ -17,7 +16,7 @@ const Breadcrumb: React.FC<Props> = ({ links, children }) => {
       <ul>
         {links &&
           links.map(({ label, href }) => (
-            <li key={v4()}>
+            <li key={href}>
               <NavLink to={href}>{label}</NavLink>
             </li>
           ))}

+ 2 - 2
kafka-ui-react-app/src/redux/actions/actions.ts

@@ -5,7 +5,7 @@ import {
   BrokerMetrics,
   Cluster,
   Topic,
-  TopicConfig,
+  InputTopicConfig,
   TopicDetails,
   TopicMessage,
   TopicName,
@@ -54,7 +54,7 @@ export const fetchTopicConfigAction = createAsyncAction(
   ActionType.GET_TOPIC_CONFIG__REQUEST,
   ActionType.GET_TOPIC_CONFIG__SUCCESS,
   ActionType.GET_TOPIC_CONFIG__FAILURE
-)<undefined, { topicName: TopicName; config: TopicConfig[] }, undefined>();
+)<undefined, { topicName: TopicName; config: InputTopicConfig[] }, undefined>();
 
 export const createTopicAction = createAsyncAction(
   ActionType.POST_TOPIC__REQUEST,

+ 2 - 2
kafka-ui-react-app/src/redux/api/topics.ts

@@ -4,7 +4,7 @@ import {
   Topic,
   ClusterName,
   TopicDetails,
-  TopicConfig,
+  InputTopicConfig,
   TopicFormData,
   TopicFormCustomParam,
   TopicFormFormattedParams,
@@ -30,7 +30,7 @@ const formatCustomParams = (
 export const getTopicConfig = (
   clusterName: ClusterName,
   topicName: TopicName
-): Promise<TopicConfig[]> =>
+): Promise<InputTopicConfig[]> =>
   fetch(`${BASE_URL}/clusters/${clusterName}/topics/${topicName}/config`, {
     ...BASE_PARAMS,
   }).then((res) => res.json());

+ 6 - 1
kafka-ui-react-app/src/redux/interfaces/topic.ts

@@ -5,12 +5,16 @@ export enum CleanupPolicy {
   Compact = 'compact',
 }
 
-export interface TopicConfig {
+export interface InputTopicConfig {
   name: string;
   value: string;
   defaultValue: string;
 }
 
+export interface TopicConfig extends InputTopicConfig {
+  id: string;
+}
+
 export interface TopicConfigByName {
   byName: {
     [paramName: string]: TopicConfig;
@@ -89,6 +93,7 @@ export interface TopicFormCustomParams {
 
 export interface TopicWithDetailedInfo extends Topic, TopicDetails {
   config?: TopicConfig[];
+  id: string;
 }
 
 export interface TopicsState {

+ 7 - 2
kafka-ui-react-app/src/redux/reducers/topics/reducer.ts

@@ -1,3 +1,4 @@
+import { v4 } from 'uuid';
 import { Action, TopicsState, Topic } from 'redux/interfaces';
 import ActionType from 'redux/actionType';
 
@@ -18,6 +19,7 @@ const updateTopicList = (state: TopicsState, payload: Topic[]): TopicsState => {
     memo.byName[name] = {
       ...memo.byName[name],
       ...topic,
+      id: v4(),
     };
     memo.allNames.push(name);
 
@@ -30,7 +32,7 @@ const addToTopicList = (state: TopicsState, payload: Topic): TopicsState => {
     ...state,
   };
   newState.allNames.push(payload.name);
-  newState.byName[payload.name] = payload;
+  newState.byName[payload.name] = { ...payload, id: v4() };
   return newState;
 };
 
@@ -61,7 +63,10 @@ const reducer = (state = initialState, action: Action): TopicsState => {
           ...state.byName,
           [action.payload.topicName]: {
             ...state.byName[action.payload.topicName],
-            config: action.payload.config,
+            config: action.payload.config.map((inputConfig) => ({
+              ...inputConfig,
+              id: v4(),
+            })),
           },
         },
       };