You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React TypeScript动态修改轮播组件Section标题求助

问题

使用TypeScript开发时,需要实现:

  • 新增帖子时,Section标题显示为“ARTIKEL BARU”或“BERITA BARU”
  • 编辑旧帖子时,标题仅显示“ARTIKEL”或“BERITA”

接手现有代码后,尝试删除if else中的“TERBARU”字样但无效果,请教如何实现Section标题的动态修改。

相关代码

表格组件代码

import { useNavigate } from 'react-router';

import { Space, Card, Table, Button, Typography } from 'antd';

import { HomepageProps } from '@customTypes/dashboard';

import { ADD_CAROUSEL, EDIT_CAROUSEL } from '@constants/urls';

const { Title } = Typography;

const CarouselCard = ({ data }: { data: HomepageProps[] }) => {
  const navigate = useNavigate();

  const columns = [
    {
      title: 'Section',
      key: 'otherData',
      dataIndex: 'otherData',
      render: (text: { section: string }) => text?.section,
    },
    {
      title: 'Judul Konten',
      key: 'title',
      dataIndex: 'title',
    },
    {
      title: 'Deskripsi Konten',
      key: 'content',
      dataIndex: 'content',
    },
    {
      title: 'Aksi',
      key: 'action',
      render: (_: string, record: any) => (
        <Space align="end">
          <Button
            type="link"
            className="button-link-grey"
            onClick={() => navigate(EDIT_CAROUSEL + '/' + record.id)}
          >
            Ubah
          </Button>
        </Space>
      ),
    },
  ];
  return (
    <Space direction="vertical" size="middle" style={{ display: 'flex' }}>
      <Card
        title={
          <Space align="end">
            <Title level={4} style={{ marginBottom: 0 }}>
              Carousel
            </Title>
            {data.length < 3 && (
              <Button onClick={() => navigate(ADD_CAROUSEL)}>
                Tambah Baru
              </Button>
            )}
          </Space>
        }
      >
        <Table columns={columns} dataSource={data} pagination={false} />
      </Card>
    </Space>
  );
};

export default CarouselCard;

编辑页面代码

import { useState, useEffect } from 'react';
import { useLocation, useNavigate } from 'react-router';

import {
  Card,
  Row,
  Col,
  Space,
  Button,
  message,
  Input,
  Typography,
  Select,
} from 'antd';

import CustomTitle from '@components/Title';

import { DASHBOARD } from '@constants/urls';

import fetchRequest from '@utils/fetcher';

const { TextArea } = Input;
const { Title } = Typography;
const { Option } = Select;

type TitleProps = {
  id: string;
  title: string;
  type: 'news' | 'article' | 'publication';
};

const EditCarousel = () => {
  const [id, setId] = useState('');
  const [title, setTitle] = useState('');
  const [content, setContent] = useState('');
  const [articleList, setArticleList] = useState<TitleProps[]>([]);
  const [newsList, setNewsList] = useState<TitleProps[]>([]);
  const [publicationList, setPublicationList] = useState<TitleProps[]>([]);
  const [section, setSection] = useState('');
  


  const navigate = useNavigate();
  const location = useLocation();

  const handleSubmit = async () => {
    const titleId = [...articleList, ...newsList, ...publicationList].filter(
      (al) => al.id === title
    )[0];

    let sec = section;

    if (section === '') {
      if (titleId.type === 'news') {
        sec = 'BERITA TERBARU';
      } else if (titleId.type === 'article') {
        sec = 'ARTIKEL TERBARU';
      } else if (titleId.type === 'publication') {
        sec = 'PUBLIKASI TERBARU';
      }
    }

    const param = {
      title: titleId.title,
      content,
      section: sec,
      originId: title,
    };

    try {
      await fetchRequest({
        method: 'POST',
        path: 'resource/homepage/carousel',
        data: id !== '' ? { ...param, id } : param,
      }).then((response) => {
        if (!response.error) {
          navigate(DASHBOARD);
        } else {
          message.error(response.error.message);
        }
      });
    } catch (error) {
      message.error(error.message);
    }
  };

  const getContent = async (id: string) => {
    try {
      await fetchRequest({
        method: 'GET',
        path: 'resource?id=' + id,
      }).then((response) => {
        if (!response.error) {
          setTitle(response.title || '');
          setContent(response.content || '');
          setSection(response?.otherData?.section || '');
        } else {
          message.error(response.error.message);
        }
      });
    } catch (error) {
      message.error(error.message);
    }
  };

  const getTitleList = async (type: string) => {
    try {
      await fetchRequest({
        method: 'GET',
        path: 'info/no-content?types=' + type,
      }).then((response) => {
        if (!response.error) {
          if (type === 'news') {
            setNewsList(response || []);
          } else if (type === 'article') {
            setArticleList(response || []);
          } else if (type === 'publication') {
            setPublicationList(response || []);
          }
        } else {
          message.error(response.error.message);
        }
      });
    } catch (error) {
      message.error(error.message);
    }
  };

  const getDataList = async () => {
    let type = '';

    if (section === 'ARTIKEL TERBARU') {
      type = 'article';
    } else if (section === 'PUBLIKASI TERBARU') {
      type = 'publication';
    } else if (section === 'BERITA TERBARU') {
      type = 'news';
    }

    if (type === '') {
      getTitleList('news');
      getTitleList('publication');
      getTitleList('article');
    } else {
      getTitleList(type);
    }
  };

  useEffect(() => {
    const isEdit = 
      location.pathname.split('/').filter((pn) => pn === 'edit').length > 0;

    if (isEdit) {
      const path = location.pathname.split('/');
      const testimonyId = path[path.indexOf('edit') + 1];

      setId(testimonyId);

      getContent(testimonyId);
    }

    getDataList();
  }, []);
  return (
    <Row>
      <Col span={12} offset={6}>
        <Card>
          <Space direction="vertical" style={{ width: '100%' }}>
            <CustomTitle name={section || 'Carousel'} url={DASHBOARD} />
            <Title level={5}>Pilih judul yang akan ditampilkan</Title>
            <Select
              value={title}
              placeholder="Judul"
              onChange={(value: any) => setTitle(value)}
              style={{ width: '100%' }}
            >
              {[...articleList, ...newsList, ...publicationList].map((al) => (
                <Option key={al.id} value={al.id}>
                  {al.title}
                </Option>

              ))}
            </Select>
            <Title level={5}>Deskripsi Singkat</Title>
            <TextArea
              value={content}
              onChange={(e: any) => setContent(e.target.value)}
              rows={4}
            />
            <Row justify="end">
              <Col>
                <Button type="primary" danger onClick={() => handleSubmit()}>
                  Simpan Perubahan
                </Button>
              </Col>
            </Row>
          </Space>
        </Card>
      </Col>
    </Row>
  );
};

export default EditCarousel;

表格截图

解决方案

1. 明确新增/编辑状态

在EditCarousel组件顶部新增判断逻辑,通过id是否为空区分新增和编辑模式:

const isEdit = !!id; // id不为空即为编辑模式

2. 动态调整Section显示文本

新增一个函数处理显示用的Section文本,替换原有CustomTitle的name属性:

const getDisplaySection = () => {
  if (!section) return 'Carousel';
  
  if (isEdit) {
    // 编辑模式:移除"TERBARU"后缀
    return section.replace(' TERBARU', '');
  } else {
    // 新增模式:将"TERBARU"替换为"BARU"
    return section.replace(' TERBARU', ' BARU');
  }
};

// 替换原CustomTitle代码
<CustomTitle name={getDisplaySection()} url={DASHBOARD} />

3. 修正提交时的Section参数

修改handleSubmit中的Section赋值逻辑,确保新增和编辑时提交正确的值:

const handleSubmit = async () => {
  const titleId = [...articleList, ...newsList, ...publicationList].filter(
    (al) => al.id === title
  )[0];

  let sec = section;

  if (section === '') {
    // 新增模式:直接设置带BARU后缀的Section
    if (titleId.type === 'news') {
      sec = 'BERITA BARU';
    } else if (titleId.type === 'article') {
      sec = 'ARTIKEL BARU';
    } else if (titleId.type === 'publication') {
      sec = 'PUBLIKASI BARU';
    }
  } else if (isEdit) {
    // 编辑模式:移除TERBARU后缀,确保提交的值符合要求
    sec = sec.replace(' TERBARU', '');
  }

  // 后续提交逻辑保持不变...
};

4. 修复编辑时初始数据的Section处理

在getContent函数中,获取后端数据后直接处理编辑模式的Section:

const getContent = async (id: string) => {
  try {
    await fetchRequest({
      method: 'GET',
      path: 'resource?id=' + id,
    }).then((response) => {
      if (!response.error) {
        setTitle(response.title || '');
        setContent(response.content || '');
        const fetchedSection = response?.otherData?.section || '';
        // 编辑模式下提前移除TERBARU后缀
        setSection(isEdit ? fetchedSection.replace(' TERBARU', '') : fetchedSection);
      } else {
        message.error(response.error.message);
      }
    });
  } catch (error) {
    message.error(error.message);
  }
};

5. 兼容Section判断逻辑

修改getDataList中的类型判断,同时兼容带后缀和不带后缀的Section值:

const getDataList = async () => {
  let type = '';

  if (section.includes('ARTIKEL')) {
    type = 'article';
  } else if (section.includes('PUBLIKASI')) {
    type = 'publication';
  } else if (section.includes('BERITA')) {
    type = 'news';
  }

  if (type === '') {
    getTitleList('news');
    getTitleList('publication');
    getTitleList('article');
  } else {
    getTitleList(type);
  }
};

6. 更新useEffect依赖

将isEdit加入useEffect的依赖数组,确保编辑状态变化时能重新获取数据:

useEffect(() => {
  const editFlag = location.pathname.split('/').filter((pn) => pn === 'edit').length > 0;

  if (editFlag) {
    const path = location.pathname.split('/');
    const testimonyId = path[path.indexOf('edit') + 1];
    setId(testimonyId);
    getContent(testimonyId);
  }

  getDataList();
}, [isEdit]); // 添加isEdit作为依赖

内容的提问来源于stack exchange,提问作者Estherak23

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 21:35:53