Javascript 反应复合成分-如何反应儿童?

Javascript 反应复合成分-如何反应儿童?,javascript,reactjs,Javascript,Reactjs,我对复合组件设计有问题。 我有一个定义道具的包装器组件。 我使用Context.Provider为子内容组件提供道具。我希望内容组件的子组件对21作出反应{answer} 限制:我想使用函数组件、钩子、无Redux、无Renderprops。没有HOC const App = () => { return ( <div className="App"> <Wrapper answer={21}> {/* I want to d

我对复合组件设计有问题。 我有一个定义道具的包装器组件。 我使用Context.Provider为子内容组件提供道具。我希望内容组件的子组件对21作出反应{answer}

限制:我想使用函数组件、钩子、无Redux、无Renderprops。没有HOC

const App = () => {
  return (
    <div className="App">
      <Wrapper answer={21}>
        {/* I want to do this below: <p>the answer is {answer}</p> */}
        <Content>
          <p>the answer is answer</p>
        </Content>
      </Wrapper>
    </div>
  );
};

const WrapperContext = createContext();

const Wrapper = ({ children, ...props }) => {
  return (
    <WrapperContext.Provider
      value={{
        ...props
      }}
    >
      {children}
    </WrapperContext.Provider>
  );
};

const Content = ({ children }, ...remainingProps) => {
  const wrapperProps = useContext(WrapperContext);


  return (
    <Wrapper>
      <Card>
        <div id="dialog-description">
          {children}
        </div>
      </Card>
    </Wrapper>
  );
};
const-App=()=>{
返回(
{/*我想在下面这样做:答案是{answer}

*/} 答案就是答案

); }; const WrapperContext=createContext(); 常量包装器=({children,…props})=>{ 返回( {儿童} ); }; 常量内容=({children},…remainingProps)=>{ const wrapperProps=useContext(WrapperContext); 返回( {儿童} ); };


{/*我想在下面这样做:答案是{answer}

*/} 答案就是答案

因此,显而易见的答案是直接内联执行,如
中所示,答案是21

。如果合适,21可以来自使用两次的变量。基本上,应用程序知道它需要使用21,让它把它传递到两个需要它的地方

const App = () => {
  const answer = 21;
  return (
    <div className="App">
      <Wrapper answer={answer}>
        <Content>
          <p>the answer is {answer}</p>
        </Content>
      </Wrapper>
    </div>
  );
};
const-App=()=>{
常数回答=21;
返回(
答案是{答案}

); };
但我猜您试图解决的实际情况是,包装器位于组件树的更高部分,因此您不知道传递给
的内容。因此,内容的工作将是从上下文中获取值,然后使用它进行渲染。但为了做到这一点,您需要在内容组件和应用程序组件之间进行双向通信。内容需要告诉应用程序“这是我从上下文中获得的值”,然后应用程序可以说“这是给定该值我想要呈现的内容”

换句话说,您需要一个渲染道具,但这是您明确排除的可能性。如果你愿意接受这种可能性,下面是它的样子

const App = () => {
  return (
    <div className="App">
      <Wrapper answer={21}>
        <Content>
          {({ answer }) => <p>the answer is {answer}</p>}
        </Content>
      </Wrapper>
    </div>
  );
};

const Content = ({ children }, ...remainingProps) => {
  const wrapperProps = useContext(WrapperContext);


  return (
    <Wrapper>
      <Card>
        <div id="dialog-description">
          {children(wrapperProps)}
        </div>
      </Card>
    </Wrapper>
  );
};

Content.propTypes = {
  children: PropTypes.func.isRequired,
}
const-App=()=>{
返回(
{({answer})=>答案是{answer}

} ); }; 常量内容=({children},…remainingProps)=>{ const wrapperProps=useContext(WrapperContext); 返回( {儿童(包装道具)} ); }; Content.propTypes={ 子项:需要PropTypes.func.isRequired, }

{/*我想在下面这样做:答案是{answer}

*/} 答案就是答案

因此,显而易见的答案是直接内联执行,如
中所示,答案是21

。如果合适,21可以来自使用两次的变量。基本上,应用程序知道它需要使用21,让它把它传递到两个需要它的地方

const App = () => {
  const answer = 21;
  return (
    <div className="App">
      <Wrapper answer={answer}>
        <Content>
          <p>the answer is {answer}</p>
        </Content>
      </Wrapper>
    </div>
  );
};
const-App=()=>{
常数回答=21;
返回(
答案是{答案}

); };
但我猜您试图解决的实际情况是,包装器位于组件树的更高部分,因此您不知道传递给
的内容。因此,内容的工作将是从上下文中获取值,然后使用它进行渲染。但为了做到这一点,您需要在内容组件和应用程序组件之间进行双向通信。内容需要告诉应用程序“这是我从上下文中获得的值”,然后应用程序可以说“这是给定该值我想要呈现的内容”

换句话说,您需要一个渲染道具,但这是您明确排除的可能性。如果你愿意接受这种可能性,下面是它的样子

const App = () => {
  return (
    <div className="App">
      <Wrapper answer={21}>
        <Content>
          {({ answer }) => <p>the answer is {answer}</p>}
        </Content>
      </Wrapper>
    </div>
  );
};

const Content = ({ children }, ...remainingProps) => {
  const wrapperProps = useContext(WrapperContext);


  return (
    <Wrapper>
      <Card>
        <div id="dialog-description">
          {children(wrapperProps)}
        </div>
      </Card>
    </Wrapper>
  );
};

Content.propTypes = {
  children: PropTypes.func.isRequired,
}
const-App=()=>{
返回(
{({answer})=>答案是{answer}

} ); }; 常量内容=({children},…remainingProps)=>{ const wrapperProps=useContext(WrapperContext); 返回( {儿童(包装道具)} ); }; Content.propTypes={ 子项:需要PropTypes.func.isRequired, }
限制:我想使用函数组件、钩子、无Redux、无Renderprops。没有HOC

const App = () => {
  return (
    <div className="App">
      <Wrapper answer={21}>
        {/* I want to do this below: <p>the answer is {answer}</p> */}
        <Content>
          <p>the answer is answer</p>
        </Content>
      </Wrapper>
    </div>
  );
};

const WrapperContext = createContext();

const Wrapper = ({ children, ...props }) => {
  return (
    <WrapperContext.Provider
      value={{
        ...props
      }}
    >
      {children}
    </WrapperContext.Provider>
  );
};

const Content = ({ children }, ...remainingProps) => {
  const wrapperProps = useContext(WrapperContext);


  return (
    <Wrapper>
      <Card>
        <div id="dialog-description">
          {children}
        </div>
      </Card>
    </Wrapper>
  );
};
渲染道具和HOC不是品味问题,而是常见问题的既定解决方案。在需要时不使用它们将导致代码质量低下

丑陋的解决方法是使用文本模板,比如
答案是{answer}

,然后对它们进行处理。下面是一个硬编码用于独生子女的示例:

const Content = ({ children }, ...remainingProps) => {
  const wrapperProps = useContext(WrapperContext);
  const theOnlyChild = React.cloneElement(children, {}, 
    children.props.children.replace('{answer}`, wrapperProps.answer);
  );

  return (
    <Wrapper>
      {theOnlyChild}
    </Wrapper>
  );
};
用起来像:

  <Wrapper answer={21}>
    <Content>{({ answer }) => (
      <p>the answer is {answer}</p>
    )}</Content>
  </Wrapper>

{({答案})=>(
答案是{答案}

)}
这基本上就是
WrapperContext.Consumer
的用途,因此
Wrapper
Content
组件可能是多余的

限制:我想使用函数组件、钩子、无Redux、无Renderprops。没有HOC

const App = () => {
  return (
    <div className="App">
      <Wrapper answer={21}>
        {/* I want to do this below: <p>the answer is {answer}</p> */}
        <Content>
          <p>the answer is answer</p>
        </Content>
      </Wrapper>
    </div>
  );
};

const WrapperContext = createContext();

const Wrapper = ({ children, ...props }) => {
  return (
    <WrapperContext.Provider
      value={{
        ...props
      }}
    >
      {children}
    </WrapperContext.Provider>
  );
};

const Content = ({ children }, ...remainingProps) => {
  const wrapperProps = useContext(WrapperContext);


  return (
    <Wrapper>
      <Card>
        <div id="dialog-description">
          {children}
        </div>
      </Card>
    </Wrapper>
  );
};
渲染道具和HOC不是品味问题,而是常见问题的既定解决方案。在需要时不使用它们将导致代码质量低下

丑陋的解决方法是使用文本模板,比如
答案是{answer}

,然后对它们进行处理。下面是一个硬编码用于独生子女的示例:

const Content = ({ children }, ...remainingProps) => {
  const wrapperProps = useContext(WrapperContext);
  const theOnlyChild = React.cloneElement(children, {}, 
    children.props.children.replace('{answer}`, wrapperProps.answer);
  );

  return (
    <Wrapper>
      {theOnlyChild}
    </Wrapper>
  );
};
用起来像:

  <Wrapper answer={21}>
    <Content>{({ answer }) => (
      <p>the answer is {answer}</p>
    )}</Content>
  </Wrapper>

{({答案})=>(
答案是{答案}

)}

这就是
WrapperContext.Consumer
的基本功能,因此
Wrapper
Content
组件可能是多余的。

您想要实现什么?我觉得有更简单的方法去做。我想更简单。我希望使应用程序组件尽可能简单,并将复杂性隐藏在封闭的组件中。这