首页 > 解决方案 > 为什么我的道具在发送到组件时未定义?

问题描述

我的项目中有一个表格,并且我有一个可以从该表格访问的编辑/查看/添加页面。我的目标是将点击的数据毫无问题地发送到其他组件,但无论我多么努力,我都会收到未定义的错误并且项目已损坏。如果您能提供帮助,我会很高兴。

我正在从父组件到子组件共享我的代码

表页。

import React, { useState, useEffect, useCallback, useMemo } from "react";
import ManagementTable from '../components/ManagementTable'
import {
  getApps,
  updateStopRisk,
  countLiveCountry,
  updateAppShow,
  deleteApp,
} from "../api/apiCalls";
import VisibilityIcon from "@material-ui/icons/Visibility";
import DeleteIcon from "@material-ui/icons/Delete";
import EditIcon from "@material-ui/icons/Edit";
import Switch from "@material-ui/core/Switch";
import DeleteModal from "../components/DeleteModal";
import { Link } from "react-router-dom";

const Management = () => {
  const [apps, setApps] = useState([]);
  const [modalVisible, setModalVisible] = useState(false);
  const [currentApp, setCurrentApp] = useState("");
  const [appID, setAppID] = useState(0);

  const fetchData = useCallback(async () => {
    const { data: appsResponse } = await getApps();
    const countLiveCountries = await fetchLiveCountriesForApps(appsResponse);
    setApps(
      appsResponse.map((app, idx) => ({
        ...app,
        countLiveCountry: countLiveCountries[idx],
      }))
    );

  }, []);

  useEffect(() => {
    fetchData();

  }, [fetchData]);

  const fetchLiveCountriesForApps = async (appwLive) => {
    const countLiveCountries = await Promise.all(
      appwLive.map((app) => countLiveCountry(app.appID))
    );
    return countLiveCountries.map(({ data: liveCountries }) => liveCountries);
  };

  const removeApp = async () => {
    await deleteApp(appID);
    setModalVisible(false);
    fetchData();
  };

  const onClickCancel = () => {
    setModalVisible(false);
  };

  const columns = useMemo(() => [
    {
      Header: "Application Name",
      accessor: "app_name",
    },
    {
      Header: "Business Area",
      accessor: "businessarea.businessarea_name",
    },
    {
      Header: "Live Plants",
      accessor: "countLiveCountry",
    },
    {
      Header: "Line Stop Risk",
      accessor: "app_stoprisk",
      Cell: ({ row: { original } }) => {

        const changeCheck = async (id) => {
          await updateStopRisk(id);
          fetchData();
        };
        return (
          <input
            checked={original.app_stoprisk}
            onClick={() => {
              changeCheck(original.appID);
            }}
            id="appStopRisk"
            type="checkbox"
            style={{ width: 18, height: 18, marginTop: 5 }}
          />
        )
      },
      sortType: (a, b, id) => {
        if (a.original[id] > b.original[id]) return -1;
        if (b.original[id] > a.original[id]) return 1;
      },
    },
    {
      Header: "Actions",
      Cell: ({ row: { original } }) => {
        const changeTrack = async (id) => {
          await updateAppShow(id);
          fetchData();
        };
        return (
          <>
            <Link
              className="btn btn-manage-link btn-sm col-2"
              to={{
                pathname: `/management/${original.app_name}`,
                mode: "view",
                id: original.appID
              }}
            >
              <VisibilityIcon></VisibilityIcon>
            </Link>
            <Link
              to={{
                pathname: `/management/${original.app_name}`,
                mode: "edit",
                id: original.appID
              }}
              className="btn btn-manage-link btn-sm col-2"
            >
              <EditIcon></EditIcon>
            </Link>
            <button
              onClick={() => {
                setModalVisible(true);
                setCurrentApp(original.app_name);
                setAppID(original.appID);
              }}
              className="btn btn-manage-link btn-sm col-3"
            >
              <DeleteIcon></DeleteIcon>
            </button>
            <Switch
              onClick={() => changeTrack(original.appID)}
              checked={original.app_show}
              className="col-3"
            ></Switch>
          </>
        )
      },
    },
  ],
    [fetchData]
  );

  return (
    <div className="container">
      <h2 style={{ float: "left", font: "bold" }}>Management</h2>
      <div style={{ float: "right" }}>
        <Link className="btn btn-danger btn-sm" to={{ pathname: `/management/add`, mode: "add" }}>
          Add New App
          </Link>
        <Link className="btn btn-danger btn-sm ml-3" exact to="/management/plants">
          Plant Management
          </Link>
      </div>
      <ManagementTable columns={columns} data={apps} />
      <DeleteModal
        message={<strong>{currentApp}</strong>}
        variety="app"
        onClickCancel={onClickCancel}
        onClickOk={removeApp}
        visible={modalVisible}
      />
    </div>
  );
};

export default Management;

我转移道具的页面。

import React, { useState, useEffect } from "react";
import Accordion from "../components/Accordion";
import Details from '../components/Details'
import {
  getByIdApps,
} from "../api/apiCalls";

const ApplicationManagement = (props) => {

  const [appById, setAppById] = useState([]);
  const { id } = props.location;
  const [selectOption, setSelectOption] = useState('add')

  useEffect(() => {
    getData();
    getMode();
  }, [])

  const getData = async () => {
    console.log(props.location.id)
    if (props.location.id) {
      await getByIdApps(props.location.id).then((response) => setAppById(response.data))
      console.log(appById)
      console.log(props)
    }
    else {
      setSelectOption('add')
    }
  }

  const getMode = () => props.location.mode ? setSelectOption(props.location.mode) : setSelectOption('add')

  const handleOptionChange = (event) => {
    console.log(event.target.value)
    setSelectOption(event.target.value)
  }

  return (
    <>
      <div style={{ margin: 20 }}>
        <h1>
          {appById.app_shortcode} - {appById.app_fullname}
        </h1>
        <div className="float-right mb-auto">
          <label><input type="radio" value="view" checked={selectOption === 'view'} onChange={handleOptionChange} />View</label>
          <label> <input type="radio" value="add" checked={selectOption === 'add'} onChange={handleOptionChange} />Add</label>
          <label> <input type="radio" value="edit" checked={selectOption === 'edit'} onChange={handleOptionChange} />Edit</label>
        </div>
        <br></br>
        
          <div style={{ marginLeft: 50, marginRight: 50 }} >
            <Accordion
              title={
                <div style={{ width: 1350 }}>
                  <h3>Details</h3>
                  <hr style={{ backgroundColor: "#aaa" }}></hr>
                </div>
              }
              content={
                <Details appID={id} data = {appById}></Details>
              }
            />
            <Accordion title={
              <div style={{ width: 1350 }}>
                <h3>Links</h3>
                <hr style={{ backgroundColor: "#aaa" }}></hr>
              </div>
            }></Accordion>
            <Accordion title={
              <div style={{ width: 1350 }}>
                <h3>Factory Management</h3>
                <hr style={{ backgroundColor: "#aaa" }}></hr>
              </div>
            }></Accordion>
            <Accordion title={
              <div style={{ width: 1350 }}>
                <h3>Issues Management</h3>
                <hr style={{ backgroundColor: "#aaa" }}></hr>
              </div>
            }></Accordion>
            <Accordion title={
              <div style={{ width: 1350 }}>
                <h3>Middleware Management</h3>
                <hr style={{ backgroundColor: "#aaa" }}></hr>
              </div>
            }></Accordion>
          </div>) 
          
          {selectOption === 'add'  ? (
            <div>
              Add Mode
            </div>
          ) : selectOption === 'view' ?  (<div>View Mode</div>) : (<div>eidt</div>)}
      </div>
    </>
  );
};

export default ApplicationManagement;

以及详细信息保存在 ApplicationManagement 页面上的部分(我的代码很长,我只是分享问题部分。)

import React, { useState, useEffect } from 'react'
import axios from "axios";

import {
  getResponsibleTeams,
  getBusinessAreas
} from '../api/apiCalls'


const Details = (props) => {

  const [rTeams, setrTeams] = useState([]);
  const [bAreas, setbAreas] = useState([]);


  const { data } = props;

  useEffect(() => {
    async function fetchData() {
      const getrTeams = await getResponsibleTeams();
      const getbAreas = await getBusinessAreas();
      axios.all([getrTeams, getbAreas]).then(
        axios.spread((...allData) => {
          const allrTeams = allData[0].data;
          const allbAreas = allData[1].data;
          setrTeams(allrTeams);
          setbAreas(allbAreas);
        })
      );
    }
    fetchData();
  }, []);

  return (
    <div>
      <div
        style={{
          float: "left",
          width: 1350,
          height: 340,
        }}
      >
          <div className="form-group">
            <label style={{ float: "left" }} htmlFor="appFullName">
              Frontend:{" "}
            </label>
            <input
              id="appFullName"
              type="text"
              class="form-control"
              placeholder="dsfdsdsf"
              value={data.frontend.frontend_name} // error here
              //onChange={handleInputChange}
              name="appShortCode"
              style={{ width: 400, marginLeft: 150 }}
            />
          </div>

      </div>
    </div>
  )
}

export default Details;


标签: reactjsreact-routeraxiosreact-hooks

解决方案


后来我意识到使用异步函数会导致一些问题。我想出了一个解决方案,问题就解决了。

错误代码在这里:

<Accordion
              title={
                <div style={{ width: 1350 }}>
                  <h3>Details</h3>
                  <hr style={{ backgroundColor: "#aaa" }}></hr>
                </div>
              }
              content={
                <Details appID={id} data = {appById}></Details>
              }
            />

以及问题的解决方案


{appById &&
            <Accordion
              title={
                <div style={{ width: 1350 }}>
                  <h3>Details</h3>
                  <hr style={{ backgroundColor: "#aaa" }}></hr>
                </div>
              }
              content={
                <Details appID={id} data = {appById}></Details>
              }
            />}


推荐阅读