簡體   English   中英

是否可以將此 HoC 模式轉換為 React Hook 語法?

[英]Is it possible to turns this HoC pattern into a React Hook syntax?

我正在嘗試創建一個可重用的組件,它會改變它的行為——本質上是渲染到 SVG 或 Canvas。 我目前正試圖通過將它包裝在一個 HoC 中來做到這一點(但是我正在嘗試使用 React 鈎子),所以這一切都顯得有些平淡。


使用額外信息進行編輯

使用當前方法(HoC 返回函數),我收到以下錯誤:

函數作為 React 子元素無效。 如果您返回 Component 而不是從 render 返回,則可能會發生這種情況。 或者,您可能打算調用此函數而不是返回它。

如果我刪除了 HoC 中的函數調用:

React.jsx:類型無效——需要一個字符串(對於內置組件)或一個類/函數(對於復合組件)但得到:對象


我已經看到了一個將 HoC 轉換為 React 鈎子的例子,但我正在努力弄清楚如何轉換它 - 如果它甚至可能並且想知道是否有人可以給我一個指針? 我可能試圖以錯誤的方式構建它,因為它感覺像是一個相當復雜的用例。

所以我現在有這兩個 HoC,我覺得我需要以某種方式重構以使用稱為withSVGwithCanvas鈎子。 他們設置了不同的 DOM 來表示,重要的是有一個叫做renderLoop的函數,它需要從下面的 Scatter 組件中調用。

有點古怪,因為Scatter現在只是業務邏輯(利用 useEffect 中的依賴項),它實際上不需要返回任何 DOM,因為它只是操作父 HoC 的 DOM。 我期待在未來有更多像Scatter這樣的組件,所以不想把這個邏輯移到 HoCs 中(如果他們甚至是這樣做的正確方法)。

 const duration = 2000; const withSVG = ({ width, height, ...props }) => WrappedComponent => { const layer = useRef(null); return (props) => ( <g width={width} height={height} ref={layer}> <WrappedComponent {...props} layer={layer} /> </g> ); }; const withCanvas = ({ width, height, ...props }) => WrappedComponent => { const layer = useRef(null); const canvas = useRef(null); const renderLoop = getRenderLoop(canvas.current, width, height); return (props) => ( <React.Fragment> <custom ref={layer}/> <canvas width={width} height={height} ref={canvas}></canvas> <WrappedComponent {...props} layer={layer} renderLoop={renderLoop} /> </React.Fragment> ); }; const Scatter = ({ data, layer, renderLoop }) => { useEffect(() => { if (!layer.current) { return; } // D3 data join const join = d3 .select(layer.current) .selectAll("circle") .data(data, d => d.key); // Shrink the circles to 0 size const exit = join.exit() .transition("radius") .duration(duration) .attr("r", 0) .remove(); const enter = join.enter() .append("circle") .attr("cx", d => dx) .attr("cy", d => dy) .attr("r", 0) .style("fill", d => d.color); const update = enter .merge(join) .transition("radius") .duration(duration) .attr("cx", d => dx) .attr("cy", d => dy) .attr("r", 30) .style("fill", d => d.color); if (renderLoop) { renderLoop(exit, update); } }, [layer, data]); return null; }; const CanvasScatter = withCanvas(Scatter); const SVGScatter = withSVG(Scatter); // index.js const width = 400; const height = 400; const App = () => { const [data, setData] = useState([ { key: 1, x: 50, y: 50, color: "red" }, { key: 2, x: 150, y: 150, color: "blue" }, ]); setTimeout(() => { setData([ { key: 1, x: 100, y: 100, color: "orange" }, { key: 3, x: 150, y: 50, color: "green" }, ]); }, 3000); return ( <div> <svg width={width} height={height}> <SVGScatter width={width} height={height} data={data} /> </svg> <CanvasScatter width={width} height={height} data={data} /> </div> ); // return <div>Hello React,Webpack 4 & Babel 7!</div>; }; ReactDOM.render(<App />, document.querySelector("#root"));
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script> <div id="root"></div>

問題

我認為您的高階組件格式不正確。 看起來你已經定義了它們來消耗一些道具,然后是一個要包裝的組件。

const withSVG = ({ width, height, ...props }) => WrappedComponent => {...}

但是您按預期調用它們

const SVGScatter = withSVG(Scatter);

這里首先使用Scatter組件,HOC 嘗試從中解構值並返回一個函數來使用一個undefined的組件。 我認為這會導致您看到的錯誤。

解決方案

基於你如何使用裝飾組件

<SVGScatter width={width} height={height} data={data} />
<CanvasScatter width={width} height={height} data={data} />

我認為您的意思是從內部組件(由 HOC 返回的組件)解構widthheight

const withSVG = WrappedComponent => ({ width, height, ...props }) => {
  const layer = useRef(null);

  return (
    <g width={width} height={height} ref={layer}>
      <WrappedComponent
        layer={layer}
        {...props} // <-- data passed here
      />
    </g>
  );
};

const withCanvas = WrappedComponent => ({ width, height, ...props }) => {
  const layer = useRef(null);
  const canvas = useRef(null);
  const renderLoop = getRenderLoop(canvas.current, width, height);

  return (
    <React.Fragment>
      <custom ref={layer}/>
      <canvas width={width} height={height} ref={canvas}></canvas>
      <WrappedComponent
        layer={layer}
        renderLoop={renderLoop}
        {...props} // <-- data passed here
      />
    </React.Fragment>
  );
};

暫無
暫無

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

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