React中如何将子组件ID传递给调用API的父组件
React Table子组件调用Redux删除API失效问题
问题描述
我是React JS初学者,在此先向各位表示感谢。
我在项目中使用React Table开发数据列表,删除按钮放在子组件TablesTableRow.js中,但直接在该子组件内调用删除API无法正常运行;把相同的删除逻辑放到父组件AllLeads.js中调用则可正常工作。我需要实现点击按钮调用API删除对应列表元素的功能,以下是项目相关代码:
相关代码
数据映射组件(LeadsTable.js)
该组件负责接收列表数据,完成表头、表格行的遍历渲染:
import { Table, Tbody, Text, Th, Thead, Tr, useColorModeValue, } from "@chakra-ui/react"; // Custom components import Card from "../Card/Card.js"; import CardBody from "../Card/CardBody.js"; import TablesTableRow from "./TablesTableRow"; import React from "react"; const LeadsTable = ({captions, data }) => { const textColor = useColorModeValue("gray.700", "white"); return ( <Card overflowX={{ sm: "scroll" }} p={6} borderRadius='lg' h={"85vh"}> <CardBody> <Table variant='simple' color={textColor} > <Thead> <Tr my='.8rem' pl='0px' color='gray.400'> {captions.map((caption, idx) => { return ( <Th color='gray.400' key={idx} ps={idx === 0 ? "0px" : null}> {caption} </Th> ); })} </Tr> </Thead> <Tbody> {data.map((row) => { return ( <TablesTableRow key={`${row._id}`} id={`${row._id}`} name={row.name} email={row.email} phone_no={row.phone_no} domain={row.domain} lead_state={row.lead_state} lead_date={row.lead_date} graduation_status={row.graduation_status} /> ); })} </Tbody> </Table> </CardBody> </Card> ); }; export default LeadsTable;
表格行操作组件(TablesTableRow.js)
该组件渲染单行数据,包含编辑、删除操作按钮,最初的删除逻辑写在该组件中:
import React, { useEffect } from "react"; import { Badge, Button, Flex, Td, Text, Tr, useColorModeValue, } from "@chakra-ui/react"; import { Link } from 'react-router-dom'; import { useDispatch } from "react-redux"; import { deleteLeadsAdmin, getLeadsById } from "../../redux/Leads/actionCreator"; const TablesTableRow = (props) => { // 错误点:此处未执行useDispatch(),仅赋值了Hook本身 const dispatch = useDispatch const {id, name, email, phone_no, lead_state, lead_date, graduation_status } = props; const textColor = useColorModeValue("gray.700", "white"); const colorStatus = useColorModeValue("white", "gray.400"); const createdProjectDate = lead_date.split("T", 1); const onDeleteLead = (e)=>{ e.preventDefault(); console.log(id,'id') dispatch(deleteLeadsAdmin(id)).then(res=>{ console.log(res,'leads deleted by is') }) } return ( <Tr> <Td pl="0px"> <Flex align="center" py=".8rem" minWidth="100%" flexWrap="nowrap"> <Flex direction="column"> <Text fontSize="md" color={textColor} fontWeight="bold" minWidth="100%" > {name} </Text> </Flex> </Flex> </Td> <Td> <Flex direction="column"> <Text fontSize="sm" color={textColor} fontWeight="normal"> {email} </Text> </Flex> </Td> <Td> <Flex direction="column"> <Text fontSize="sm" color={textColor} fontWeight="normal"> {phone_no} </Text> </Flex> </Td> <Td> <Badge bg={lead_state === 0 ? 'pink.500' : lead_state === 1 ? 'green.400' : lead_state === 2 ? 'gray.600' : 'orange.200'} color={lead_state === 0 && 1 && 2 ? 'white' : colorStatus} fontSize="16px" p="3px 10px" borderRadius="8px" > {lead_state === 0 ? 'Raw Lead' : lead_state === 1 ? 'Converted Leads' : lead_state === 2 ? 'Registerd Leads' : '-'} </Badge> </Td> <Td> <Flex direction="column"> <Text fontSize="sm" color={textColor} fontWeight="normal"> {graduation_status} </Text> </Flex> </Td> <Td> <Flex direction="column"> <Text fontSize="sm" color={textColor} fontWeight="normal"> {createdProjectDate} </Text> </Flex> </Td> <Td> <Button p="0px" bg="transparent" variant="hover" _hover={{ bg: "#1e91ff", color: "#fff" }} me="10px"> <Link to={`/leads/all-leads/${id}`} > <Text fontSize="md" color={textColor} fontWeight="bold" cursor="pointer" _hover={{ color: "#fff" }} p={5} > Edit </Text> </Link> </Button> <Button p="0px" bg="transparent" variant="hover" _hover={{ bg: "#f54b4b", color: "#fff" }} onClick={onDeleteLead}> <Link to={`/leads/all-leads/${id}`} > <Text fontSize="md" color={textColor} fontWeight="bold" cursor="pointer" _hover={{ color: "#fff" }} p={5} > Delete </Text> </Link> </Button> </Td> </Tr> ); } export default TablesTableRow;
父级列表页组件(AllLeads.js)
该组件负责拉取列表数据、处理分页逻辑,在该组件内调用删除API可正常运行:
import React, { useState, useEffect } from "react"; import { Flex, WrapItem, Button, Box, useColorModeValue, } from "@chakra-ui/react"; import LeadsTable from "../../component/LeadsTable//LeadsTable"; import { useDispatch } from "react-redux"; import { deleteLeadsAdmin, getLeadsForAdmin, } from "../../redux/Leads/actionCreator"; import HeadTitle from "../../component/HeadTitle/HeadTitle"; import { BodyMain } from "../../component/HeadTitle/BodyMain"; import { useParams } from "react-router"; function AllLeads() { // 正确写法:执行useDispatch()拿到dispatch方法 const dispatch = useDispatch(); const query = useParams(); const [listingLeadsList, setListingLeadsList] = useState([]); const [pageLeads, setPageLeads] = useState(5); const chagneNextPage = () => { setPageLeads(pageLeads + 1); }; const chagnePreviousPage = () => { setPageLeads(pageLeads - 1); }; const ProjectsForAdmin = () => { dispatch(getLeadsForAdmin(pageLeads)) .then((res) => { if (res.success) { setListingLeadsList(res.data.lead); setPageLeads(res.data.next.page); } else { console.log("err Leads", res); } }) .catch((err) => console.log("errr leads", err)); }; useEffect(() => { ProjectsForAdmin(); }, []); const pagesQuantity = 12; return ( <Flex flexDirection="column" h={"100vh"} px="30px" bg={useColorModeValue("#f3f2f1", "gray.900")} > <HeadTitle title="Leads List" /> <BodyMain> <WrapItem w={"100%"}> <Box bg={useColorModeValue("#fff", "gray.800")} borderRadius="lg" w={"100%"} > <LeadsTable padding={20} title={"Leads Table"} captions={[ "Name", "Email", "Phone", "Status", "Graduation Status", "Date", "Action", ]} data={listingLeadsList} /> <Button type="submit" onClick={chagnePreviousPage}> Previous </Button> </Box> </WrapItem> </BodyMain> </Flex> ); } export default AllLeads;
解决方案
问题已解决:核心错误为Redux Hook使用不规范,子组件中写const dispatch = useDispatch时未加括号执行Hook,导致dispatch变量存储的是useDispatch函数本身,而非Redux store的派发方法。将该行修正为const dispatch = useDispatch()后,即可正常将行数据id传入API请求URL,完成删除接口调用。
注:删除按钮外层嵌套了
Link组件,点击时会默认触发路由跳转,若不需要跳转可移除删除按钮内的Link包裹,避免和删除逻辑冲突。
内容的提问来源于stack exchange,提问作者Zabric
相关产品推荐
相关产品推荐

