簡體   English   中英

如何傳遞來自不同組件(關於和聯系)的道具? 不是父母對孩子。 使用反應 typescript

[英]How to pass props from different component(about and contact)? not parent to child. Using react typescript

我試圖重用 about 組件來聯系組件。 但我無法使用道具傳遞數據。 當我調試它時,道具是未定義的。 有時錯誤是 map 未定義。

這是我的代碼

“關於組件” about.tsx

enum Color {
  Black = 'Black',
  Red = 'Red'
}

type aboutProps = {
items: string, 
backgroundColor: Color, 
minimumHeight: number, 
justify: string, 
align: string, 
fullWidth: boolean
}

const AboutComponent: FC<aboutProps> = ({items, backgroundColor, minimumHeight, justify, align, 
fullWidth}: aboutProps) => { return (
<>
<aboutContainer>
<div>
{items.map(({ heading, url, openInNewWindow, fontColor }) => {
return ( 
    <Text {...props}
    fontColor={fontColor}
    text={heading}
    url={url}
    openInNewWindow={openInNewWindow}                             
    dangerouslySetInnerHTML={{ __html: heading }}/>
    )
})}
</div>
</aboutContainer>
<>
)
}; 
export default AboutComponent;

"CONTACT COMPONENT"
contact.tsx

interface aboutProps {
items: string, 
backgroundColor: Color, 
minimumHeight: number, 
justify: string, 
align: string, 
fullWidth: boolean
}

interface contactProps extends aboutProps {
phone?: number,
name?: string,
}

const ContactComponent: FC<contactProps> = ({items, backgroundColor, minimumHeight, justify, align, fullWidth, phone, name}: contactProps) => { 

return (
    <>
     <AboutComponent items={items}
      backgroundColor = {backgroundColor}
      minimumHeight = {minimumHeight}
      justify = {justify}
      align = {align}
      fullWidth = {fullWidth}/>
    </>
)

};

export default ContactComponent;

道具未定義,例如項目、背景、最小高度、對齊、對齊、全寬

一種父子關系。 我不知道你為什么認為它不是。 ContactComponent是父組件, AboutComponent是子組件。

ContactComponent要求使用AboutComponent的所有道具調用它,並且您正確地傳遞它們。 如果您收到道具undefined的錯誤,那么該問題不在您在此處發布的代碼中。 這是您在沒有正確道具的情況下調用<ContactComponent/>


但是還有很多其他的問題。 最明顯的是道具items ——您的類型說它是一個string ,但您的代碼將其視為具有屬性{ heading, url, openInNewWindow, fontColor }的對象array 您需要 A) 要求您擁有這些對象的數組或 B) 使用children道具並在其中調用帶有<Text/>元素的AboutComponent

你不想使用dangerouslySetInnerHTML的SetInnerHTML,你真的不需要它。 除非您的Text組件正在使用此道具並使用它,否則它不會在這里做任何事情。 看起來您的Text已經在使用text道具,因此它可以創建自己的 HTML 內容。

您可能希望將一些樣式道具設為可選。 現在它們都是必需的。

這是我清理組件的嘗試:

import React, { CSSProperties, FC } from "react";

export enum Color {
  // CSS color names are lower-case
  Black = "black",
  Red = "red"
}

export type TextProps = {
  text: string;
  url: string;
  openInNewWindow?: boolean;
  fontColor?: CSSProperties["color"];
};

export const Text: FC<TextProps> = ({
  text,
  url,
  openInNewWindow = false,
  fontColor
}) => {
  return (
    <a
      href={url}
      target={openInNewWindow ? "_blank" : "_self"}
      style={{ color: fontColor, display: "block", padding: 10 }}
    >
      {text}
    </a>
  );
};

export type AboutContainerProps = {
  backgroundColor?: Color;
  minimumHeight?: number;
  justify?: string;
  align?: string;
  fullWidth?: boolean;
};

export const AboutContainer: FC<AboutContainerProps> = ({
  backgroundColor = Color.Black,
  minimumHeight,
  justify = "space-evenly",
  align = "center",
  fullWidth = true,
  children // the JSX children -- this prop is automatically included by FC
}) => {
  return (
    <div
      style={{
        background: backgroundColor,
        minHeight: minimumHeight,
        width: fullWidth ? "100%" : "auto",
        display: "flex",
        justifyContent: justify,
        alignItems: align
      }}
    >
      {children}
    </div>
  );
};

export type AboutProps = AboutContainerProps & {
  items: TextProps[];
};

export const AboutComponent: FC<AboutProps> = ({
  items,
  ...aboutProps // rest object for all other props
}: AboutProps) => {
  return (
    <AboutContainer {...aboutProps}>
      {items.map((props) => {
        return <Text key={props.text} {...props} />;
      })}
    </AboutContainer>
  );
};

export type ContactInfo = {
  phone?: number;
  name?: string;
};

export const ContactInfoComponent: FC<ContactInfo> = ({ phone, name }) => {
  if (!phone && !name) {
    return null;
  }
  //TODO: format phone number string
  return (
    <div>
      <h3>Get In Touch</h3>
      {name && <div>{name}</div>}
      {phone && <div>Call Me: {phone}</div>}
    </div>
  );
};

export type ContactProps = AboutProps & ContactInfo;

// do we really even need this component?  can't we just compose it from the other two?
export const ContactComponent: FC<ContactProps> = ({
  phone,
  name,
  ...aboutProps
}) => {
  return (
    <div>
      <ContactInfoComponent phone={phone} name={name} />
      <AboutComponent {...aboutProps} />
    </div>
  );
};

代碼沙盒鏈接

通過這種設置,您可以這樣稱呼它,其中items是 props 對象的數組。

const Test = () => (
  <ContactComponent
    minimumHeight={100}
    justify="flex-end"
    align="center"
    items={[
      {
        text: "Home",
        url: "/"
      },
      {
        text: "Facebook",
        url: "some link",
        openInNewWindow: true,
        fontColor: Color.Red
      }
    ]}
    name={"My Name"}
    phone={5555555555}
  />
);

如果數據以原始形式來自數據庫或 API,這很有意義。 但是,如果您自己編寫道具,您可能希望使用模塊化部件來調用它:

const Test = () => (
  <div>
    <ContactInfoComponent name={"My Name"} phone={5555555555} />
    <AboutContainer
      minimumHeight={100}
      justify="flex-end"
      align="center"
      fullWidth={false}
    >
      <Text url="/">Home</Text>
      <Text url="some link" openInNewWindow={true} fontColor={Color.Red}>
        Facebook
      </Text>
    </AboutContainer>
  </div>
);

因此,您將使用children道具,而不是將道具向下傳遞多個級別。

import React, { CSSProperties, FC } from "react";

export enum Color {
  // CSS color names are lower-case
  Black = "black",
  Red = "red"
}

export type TextProps = {
  url: string;
  openInNewWindow?: boolean;
  fontColor?: CSSProperties["color"];
};

export const Text: FC<TextProps> = ({
  children,
  url,
  openInNewWindow = false,
  fontColor
}) => {
  return (
    <a
      href={url}
      target={openInNewWindow ? "_blank" : "_self"}
      style={{ color: fontColor, display: "block", padding: 10 }}
    >
      {children}
    </a>
  );
};

export type AboutContainerProps = {
  backgroundColor?: Color;
  minimumHeight?: number;
  justify?: string;
  align?: string;
  fullWidth?: boolean;
};

export const AboutContainer: FC<AboutContainerProps> = ({
  backgroundColor = Color.Black,
  minimumHeight,
  justify = "space-evenly",
  align = "center",
  fullWidth = true,
  children // the JSX children -- this prop is automatically included by FC
}) => {
  return (
    <div
      style={{
        background: backgroundColor,
        minHeight: minimumHeight,
        width: fullWidth ? "100%" : "auto",
        display: "flex",
        justifyContent: justify,
        alignItems: align
      }}
    >
      {children}
    </div>
  );
};

export type ContactInfo = {
  phone?: number;
  name?: string;
};

export const ContactInfoComponent: FC<ContactInfo> = ({ phone, name }) => {
  if (!phone && !name) {
    return null;
  }
  //TODO: format phone number string
  return (
    <div>
      <h3>Get In Touch</h3>
      {name && <div>{name}</div>}
      {phone && <div>Call Me: {phone}</div>}
    </div>
  );
};

這段代碼基本相同,但我們實際上可以刪除一些組件。

代碼沙盒鏈接

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM