首页 > 解决方案 > 在 React 中使用 ANTd Modal 中的“确定”按钮

问题描述

我正在创建一个电影网站,当您单击电影卡时会显示电影的模态。我能够处理将 setActivateModal 变为 false 并关闭 Modal 的“onCancel”,但我也希望允许“Schedule”按钮执行某些操作。预期的行为是让“计划”按钮生成一个不同的表单,我可以在其中填写以“计划”带有基本表单条目的电影,然后将其发送到我的数据库。我并没有为表单而苦苦挣扎,但我正在苦苦挣扎如何使用“计划”按钮来处理生成一个表单。我不确定你是否被允许做“嵌套”模态,但任何可以处理的方式都可以。

import React, { useEffect, useState } from 'react';
import {
  Layout,
  Input,
  Row,
  Col,
  Card,
  Tag,
  Spin,
  Modal,
  Typography,
  Button,
} from 'antd';
import 'antd/dist/antd.css';

const { Content } = Layout;
const { Search } = Input;
const { Meta } = Card;
const TextTitle = Typography.Title;

const SearchBox = ({ searchHandler }) => {
  return (
    <Row>
      <Col span={12} offset={6}>
        <Search
          placeholder="Search for movies to schedule!"
          enterButton="Search"
          size="large"
          onSearch={value => searchHandler(value)}
        />
      </Col>
    </Row>
  );
};

const MovieCard = ({
  Title,
  imdbID,
  Poster,
  ShowDetails,
  DetailRequest,
  ActivateModal,
}) => {
  const clickHandler = () => {
    ActivateModal(true);
    DetailRequest(true);

    fetch(`http://www.omdbapi.com/?i=${imdbID}&apikey=xxxxxxxx`)
      .then(resp => resp)
      .then(resp => resp.json())
      .then(response => {
        DetailRequest(false);
        ShowDetails(response);
      });
  };

  return (
    <Col style={{ margin: '50px' }} span={3}>
      <div>
        <Card
          style={{ width: 300 }}
          cover={
            <img
              alt={Title}
              src={
                Poster === 'N/A'
                  ? 'https://placehold.it/198x264&text=Image+Not+Found'
                  : Poster
              }
            />
          }
          onClick={() => clickHandler()}
        >
          <Meta title={Title} />
        </Card>
      </div>
    </Col>
  );
};

const MovieDetail = ({
  Title,
  Actors,
  Released,
  Rated,
  Runtime,
  Genre,
  Poster,
  Plot,
}) => {
  return (
    <Row>
      <Col span={11}>
        <img
          src={
            Poster === 'N/A'
              ? 'https://placehold.it/198x264&text=Image+Not+Found'
              : Poster
          }
          alt={Title}
        />
      </Col>
      <Col span={13}>
        <Row>
          <Col>
            <TextTitle>{Title}</TextTitle>
          </Col>
        </Row>
        <Row style={{ marginBottom: '.7em' }}>
          <Col>{Actors}</Col>
        </Row>
        <Row style={{ marginBottom: '.7em' }}>
          <Col>
            <Tag>{Released}</Tag>
            <Tag>{Rated}</Tag>
            <Tag>{Runtime}</Tag>
            <Tag>{Genre}</Tag>
          </Col>
        </Row>
        <Row>
          <Col>{Plot}</Col>
        </Row>
      </Col>
    </Row>
  );
};

const Loader = () => (
  <div>
    <Spin />
  </div>
);

function Movies() {
  const [data, setData] = useState(null);
  const [error, setError] = useState(null);
  const [query, setQuery] = useState('');
  const [activateModal, setActivateModal] = useState(false);
  const [details, setShowDetails] = useState(false);
  const [detailRequest, setDetailRequest] = useState(false);

  useEffect(() => {
    setError(null);
    setData(null);

    fetch(`http://www.omdbapi.com/?s=${query}&apikey=xxxxxxxx`)
      .then(resp => resp)
      .then(resp => resp.json())
      .then(response => {
        if (response.Response === 'False') {
          setError(response.Error);
        } else {
          setData(response.Search);
        }
      })
      .catch(({ message }) => {
        setError(message);
      });
  }, [query]);

  return (
    <div className="Movies">
      <Layout className="layout">
        <Content>
          <div style={{ background: '#4a576e', padding: 60, minHeight: 300 }}>
            <SearchBox searchHandler={setQuery} />
            <br />
            <Row justify="center">
              {data !== null &&
                data.length > 0 &&
                data.map((result, index) => (
                  <MovieCard
                    ShowDetails={setShowDetails}
                    DetailRequest={setDetailRequest}
                    ActivateModal={setActivateModal}
                    key={index}
                    {...result}
                  />
                ))}
            </Row>
          </div>
          <Modal
            title="Details"
            centered
            visible={activateModal}
            onCancel={() => setActivateModal(false)}
            /* onOk= {() => What do I put here? */
            width={800}
            footer={[
              <Button key="cancel" onClick={() => setActivateModal(false)}>
                Cancel
              </Button>,
              <Button
                key="schedule" /* onClick={() => setActivateForm(true)} */
              >
                Schedule
              </Button>,
            ]}
          >
            {detailRequest === false ? (
              <MovieDetail {...details} />
            ) : (
              <Loader />
            )}
          </Modal>
        </Content>
      </Layout>
    </div>
  );
}

export default Movies;

标签: reactjsformsmodal-dialogantd

解决方案


假设在 App.js 中正确设置了所有路由,请添加以下更改:

将此添加到您的导入列表中:

import { Link } from "react-router-dom";

在 Movies 函数中,添加 const [activeForm, setActiveForm] = useState(false); 如下所示

function Movies() {

const [data, setData] = useState(null);
const [error, setError] = useState(null);
const [query, setQuery] = useState('');
const [activateModal, setActivateModal] = useState(false);
const [details, setShowDetails] = useState(false);
const [detailRequest, setDetailRequest] = useState(false);
const [activateForm, setActivateForm] = useState(false);

在您的函数的返回中,在“Content”标签正下方的 div 标签中,添加 ActivateForm={setActivateForm},如下所示。

                <div style={{ background: '#4a576e', padding: 60, minHeight: 300 }}>
                    <SearchBox searchHandler={setQuery} />
                    <br />
                    <Row justify="center">
                        { data !== null && data.length > 0 && data.map((result, index) => (
                            <MovieCard 
                                ShowDetails={setShowDetails} 
                                DetailRequest={setDetailRequest}
                                ActivateModal={setActivateModal}
                                ActivateForm={setActivateForm}
                                key={index} 
                                {...result} 
                            />
                        ))}
                    </Row>
                </div>

最后,在模态标签中,附加到“onOk”,同样在模态页脚中,为“onClick”添加以下内容。

                    <Modal
                    title='Details'
                    centered
                    visible={activateModal}
                    onCancel={() => setActivateModal(false)}
                    onOk={() => setActivateForm(true)}
                    width={800}
                    footer={[
                        <Button key="cancel" onClick={() => setActivateModal(false)}>
                            Cancel
                        </Button>,
                        <Button key="schedule" onClick={() =>setActivateForm(true)}><Link to='/ScheduleForm'>Schedule</Link ></Button>
                      ]}
                    >
                    { detailRequest === false ?
                        (<MovieDetail {...details} />) :
                        (<Loader />) 
                    }
                </Modal>

推荐阅读