首页 > 解决方案 > (已解决)ReactJS。如何将数据从父组件隐式传输到子组件

问题描述

我有一个水果盒。盒子的内容是由它的属性决定的。这意味着默认情况下,水果具有与它们最初放置的盒子相同的属性。如有必要,您可以分别指定每种水果的属性。

在 JSX 中使用货架配置的示例:

<FruitShelf>
 <FruitBox defaultKind="lemons" defaultSize="1">
   <Fruit/>
   <Fruit/>
   <Fruit/>
 </FruitBox>
 <FruitBox defaultKind="oranges" defaultSize="2">
   <Fruit/>
   <Fruit/>
   <Fruit kind="lemon"/>
   <Fruit size="3"/>
 </FruitBox>
</FruitShelf>

我想将 FruitBox 的参数数据作为 Fruit 组件的默认道具发送

我现在拥有的:

FruitBox.tsx

import React from 'react'
import FruitBoxStyled from './FruitBox.styled'
import Fruit from "../Fruit/Fruit.component";

interface IFruitBoxProps{
    defaultKind: string;
    defaultSize?: number;
    children: React.ReactNode;
}

export default function FruitBox({defaultKind, defaultSize, children, fruits}: IFruitBoxProps){

    return(
      <FruitBoxStyled>
          {children}
      </FruitBoxStyled>
    );
}

水果.tsx

import React from 'react'
import lemon from '../../assets/img/lemon.png'
import FruitStyled from './Fruit.styled'

interface IFruitProps {
    kind?: string;
    size?: number;
}

const defaultProps: IFruitProps = {
    kind: lemon,
    size: 2
};

export default function Fruit ({kind, size}: IFruitProps) {

    return(
      <FruitStyled size={size}>
          <img src={kind} alt=""/>
      </FruitStyled>
    );
}

Fruit.defaultProps = defaultProps;

更新:

我已经使用context解决了这个任务。首先,我使用导出到其他组件的 Providers 和 Consumers 创建文件 fruitContext.ts。FruitBox 中的两个参数解释了两个上下文:defaultKind 和 defaultSize。我不确定这个解决方案是正确的,但它有效。

FruitContext.ts

import React from "react";

const FruitKindContext = React.createContext('');
const FruitSizeContext = React.createContext(1);

const FruitKindProvider = FruitKindContext.Provider;
const FruitSizeProvider = FruitSizeContext.Provider;

const FruitKindConsumer = FruitKindContext.Consumer;
const FruitSizeConsumer = FruitSizeContext.Consumer;

export { FruitKindProvider, FruitKindConsumer, FruitSizeProvider, FruitSizeConsumer }

您可以看到 FruitBox 和 Fruit 的一些变化——我从 Provider 发送数据并从 Consumer 获取数据:

FruitBox.tsx

import React from 'react'
import FruitBoxStyled from './FruitBox.styled'
import { FruitKindProvider, FruitSizeProvider } from "../fruitContext";

interface IFruitBoxProps{
    defaultKind: string;
    defaultSize: number;
    children: React.ReactNode;
}

export default class FruitBox extends React.Component<IFruitBoxProps>{

    render() {
        return <FruitBoxStyled>
            <FruitSizeProvider value={this.props.defaultSize}>
                <FruitKindProvider value={this.props.defaultKind}>
                    {this.props.children}
                </FruitKindProvider>
            </FruitSizeProvider>
        </FruitBoxStyled>
    }
}

水果.tsx

import React from 'react'
import lemon from '../../assets/img/lemon.png'
import FruitStyled from './Fruit.styled'
import { FruitKindConsumer, FruitSizeConsumer } from "../fruitContext";

interface IFruitProps {
    kind?: string | null;
    size?: number;
}

const defaultProps: IFruitProps = {
    kind: null,
    size: 1
};

export default function Fruit ({kind, size}: IFruitProps) {

    return(
      <div>
          {
              kind != null ?
                  <FruitStyled size={size}>
                    <img src={kind} alt=""/>
                  </FruitStyled>
                  :
                  <FruitSizeConsumer>
                      {
                          (fruitBoxSize) => {
                              return (
                                  <FruitStyled size={fruitBoxSize}>
                                      <FruitKindConsumer>
                                          {
                                              (fruitBoxKind) => {
                                                  return (
                                                      <img src={fruitBoxKind} alt=""/>
                                                  )
                                              }
                                          }
                                      </FruitKindConsumer>
                                  </FruitStyled>
                              )
                          }
                      }
                  </FruitSizeConsumer>
          }
      </div>

    );
}

Fruit.defaultProps = defaultProps;

它在 App.tsx 中的外观

应用程序.tsx

import React from 'react';
import './App.css';
import Fruit from './components/Fruit/Fruit.component';
import FruitBox from './components/FruitBox/FruitBox.component';

import lemon from './assets/img/lemon.png'
import orange from './assets/img/orange.png'
import apple from './assets/img/apple.png'
import FruitShelf from "./components/FruitShelf/FruitShelf.component";

const App: React.FC = () => {
  return (
    <div className="App">
      <header className="App-header">
      <FruitShelf>
          <FruitBox defaultKind={apple} defaultSize={4}>
            <Fruit/>
            <Fruit kind={lemon} size={1}/>
            <Fruit/>
          </FruitBox>
          <FruitBox defaultKind={lemon} defaultSize={4}>
            <Fruit/>
            <Fruit/>
            <Fruit kind={orange} size={3}/>
          </FruitBox>
      </FruitShelf>
      </header>
    </div>
  );
};

export default App;

截屏:

水果长什么样

与往常一样,我希望我对这个问题的解决方案将有助于所有需要它的人。如果对你有帮助,请评价这篇文章。

标签: javascriptreactjsreact-redux

解决方案


推荐阅读