HoC with React Hooks



我正在尝试使用Context APIclass component移植到react hooks,但我无法弄清楚出现错误的具体原因是什么。

首先,我的代码:

// contexts/sample.jsx
import React, { createContext, useState, useContext } from 'react'
const SampleCtx = createContext()
const SampleProvider = (props) => {
const [ value, setValue ] = useState('Default Value')
const sampleContext = { value, setValue }
return (
<SampleCtx.Provider value={sampleContext}>
{props.children}
</SampleCtx.Provider>
)
}
const useSample = (WrappedComponent) => {
const sampleCtx = useContext(SampleCtx)
return (
<SampleProvider>
<WrappedComponent
value={sampleCtx.value}
setValue={sampleCtx.setValue} />
</SampleProvider>
)
}
export {
useSample
}

// Sends.jsx
import React, { Component, useState, useEffect } from 'react'
import { useSample } from '../contexts/sample.jsx'
const Sends = (props) => {
const [input, setInput ] = useState('')
const handleChange = (e) => {
setInput(e.target.value)
}
const handleSubmit = (e) => {
e.preventDefault()
props.setValue(input)
}
useEffect(() => {
setInput(props.value)
}, props.value)
return (
<form onSubmit={handleSubmit}>
<input value={input} onChange={handleChange} />
<button type="submit">Submit</button>
</form>
)
}

我得到的错误:

固定冲突:无效的挂钩调用。钩子只能在函数组件的主体内部调用。这可能是由于以下原因之一:1. 您可能有不匹配的 React 和渲染器版本(例如 React DOM( 2.你可能违反了钩子 3 的规则。您可能在同一应用程序中有多个 React 副本 有关如何调试和解决此问题的提示,请参阅 https://reactjs.org/warnings/invalid-hook-call-warning.html。

我的代码说明:

我使用Context API来管理状态,以前我使用class components 来制作视图。我希望结构很简单,不需要更多细节。

我认为它也应该工作,<Sends />组件被传递到useSampleHoC 函数中,并且它与sample.jsx的组件一起包装<SampleProvider>以便<Sends />可以使用SampleCtx上下文提供的props。但结果是失败。

HoC模式与React hooks一起使用是无效的吗?或者交出突变函数是无效的(即setValue通过propsuseState()(到其他组件?或者,将 2 个或更多使用hooksfunction components放在一个文件中是无效的吗?请纠正我具体原因是什么。

所以 HOC 和 Context 是不同的 React 概念。因此,让我们将其一分为二。

供应商

提供程序的主要职责是提供上下文值。上下文值通过useContext()使用

const SampleCtx = createContext({});
export const SampleProvider = props => {
const [value, setValue] = useState("Default Value");
const sampleContext = { value, setValue };
useEffect(() => console.log("Context Value: ", value)); // only log when value changes
return (
<SampleCtx.Provider value={sampleContext}>
{props.children}
</SampleCtx.Provider>
);
};

消费者。使用useContext()钩子并添加额外的道具。返回一个新组件。

const withSample = WrappedComponent => props => { // curry
const sampleCtx = useContext(SampleCtx);
return (
<WrappedComponent
{...props}
value={sampleCtx.value}
setValue={sampleCtx.setValue}
/>
);
};

然后使用 HOC:

export default withSample(Send)

由提供者和消费者(HOC(组成,我们有:

import { SampleProvider } from "./provider";
import SampleHOCWithHooks from "./send";
import "./styles.css";
function App() {
return (
<div className="App">
<SampleProvider>
<SampleHOCWithHooks />
</SampleProvider>
</div>
);
}

有关完整代码,请参阅代码沙箱。

高阶组件是接受一个组件并返回另一个组件的函数,返回的组件可以是类组件、带有钩子的功能组件,也可以没有状态逻辑。 在您的示例中,您将从 useSample 返回 jsx。

const useSample = (WrappedComponent) => {
const sampleCtx = useContext(SampleCtx)
return ( // <-- here
<SampleProvider>
<WrappedComponent
value={sampleCtx.value}
setValue={sampleCtx.setValue} />
</SampleProvider>
)
}

如果你想做一个 HOC 你可以做的是这样的

const withSample = (WrappedComponent) => {
return props => {
const sampleCtx = useContext(SampleCtx)
<WrappedComponent
value={sampleCtx.value}
setValue={sampleCtx.setValue} {...props} />
}
}

相关内容

  • 没有找到相关文章

最新更新