带有 React Hooks 的 HoC
HoC with React Hooks
我正在尝试使用 Context API
从 class 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>
)
}
我得到的错误:
Invariant Violation: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: 1. You might have mismatching versions of React and the renderer (such as React DOM) 2. You might be breaking the Rules of Hooks 3. You might have more than one copy of React in the same app See https://reactjs.org/warnings/invalid-hook-call-warning.html for tips about how to debug and fix this problem.
我的代码说明:
我使用 Context API
来管理状态,之前我使用 class component
来制作视图。我希望结构简单明了,不需要更多细节。
我认为它也应该工作,<Sends />
组件被传递到 useSample
HoC 函数,并且它被 sample.jsx
的 <SampleProvider>
组件包裹,所以<Sends />
可以使用 SampleCtx
上下文提供的 props
。但结果是失败。
HoC
模式与 React hooks
一起使用是否无效?还是通过props
将变异函数(即useState()
制作的setValue
)交给其他组件无效?或者,在单个文件中使用 hooks
放置 2 个或更多 function components
是否无效?具体原因请指正
高阶组件是接受一个组件和 returns 另一个组件的函数,返回的组件可以是 class 组件,一个带钩子的功能组件,或者它可以没有全状态逻辑。
在您的示例中,您从 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} />
}
}
所以 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>
);
};
HOC
消费者。使用 useContext()
钩子并添加额外的道具。 Returns 一个新组件。
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>
);
}
有关完整代码,请参阅 Code Sandbox。
我正在尝试使用 Context API
从 class 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>
)
}
我得到的错误:
Invariant Violation: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: 1. You might have mismatching versions of React and the renderer (such as React DOM) 2. You might be breaking the Rules of Hooks 3. You might have more than one copy of React in the same app See https://reactjs.org/warnings/invalid-hook-call-warning.html for tips about how to debug and fix this problem.
我的代码说明:
我使用 Context API
来管理状态,之前我使用 class component
来制作视图。我希望结构简单明了,不需要更多细节。
我认为它也应该工作,<Sends />
组件被传递到 useSample
HoC 函数,并且它被 sample.jsx
的 <SampleProvider>
组件包裹,所以<Sends />
可以使用 SampleCtx
上下文提供的 props
。但结果是失败。
HoC
模式与 React hooks
一起使用是否无效?还是通过props
将变异函数(即useState()
制作的setValue
)交给其他组件无效?或者,在单个文件中使用 hooks
放置 2 个或更多 function components
是否无效?具体原因请指正
高阶组件是接受一个组件和 returns 另一个组件的函数,返回的组件可以是 class 组件,一个带钩子的功能组件,或者它可以没有全状态逻辑。 在您的示例中,您从 useSample.
返回 jsxconst 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} />
}
}
所以 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>
);
};
HOC
消费者。使用 useContext()
钩子并添加额外的道具。 Returns 一个新组件。
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>
);
}
有关完整代码,请参阅 Code Sandbox。