我正在尝试将class component
从react hooks
移植到Context API
,但我不知道导致错误的具体原因是什么。
// 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 component
来进行视图。我希望结构简单明了,不需要更多细节。
我认为它也应该工作,<Sends />
组件被传递到useSample
HoC函数中,并被<SampleProvider>
的{{1}}组件包装,因此{ {1}}可以使用sample.jsx
上下文提供的<Sends />
。但是结果就是失败。
将props
模式与SampleCtx
一起使用是否无效?还是通过HoC
将变异函数(即React hooks
产生的setValue
传递给其他组件是否无效?还是在单个文件中使用useState()
放置两个或更多props
是无效的吗?请纠正我的具体原因。
答案 0 :(得分:2)
高阶组件是接受一个组件并返回另一个组件的函数,而返回的组件可以是类组件,带有钩子的功能组件,也可以没有全状态逻辑。 在您的示例中,您将从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} />
}
}
答案 1 :(得分:1)
因此,HOC和上下文是不同的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>
);
};
HOC
消费者。使用useContext()
钩子并添加其他道具。返回一个新组件。
const useSample = WrappedComponent => props => { // curry
const sampleCtx = useContext(SampleCtx);
return (
<WrappedComponent
{...props}
value={sampleCtx.value}
setValue={sampleCtx.setValue}
/>
);
};
然后使用HOC:
export default useSample(Send)
堆肥提供者和消费者(HOC),我们有:
import { SampleProvider } from "./provider";
import SampleHOCWithHooks from "./send";
import "./styles.css";
function App() {
return (
<div className="App">
<SampleProvider>
<SampleHOCWithHooks />
</SampleProvider>
</div>
);
}
有关完整代码,请参见Code Sandbox。