我有一个组件,单击按钮即可通过props.OnValChange
将更新后的值发送给父级。这是在useEffect
挂钩中实现的。
如果我在控制台上记录useEffect,则可以看到它正在被调用。但是在我进行的测试中,expect(prop.OnValChange).toHaveBeenCalledTimes(1);
表示被调用0次。
组件:
const MyComp = ({OnValChange}) => {
const [ val, setVal ] = useState(0);
useEffect(() => {
console.log("before");
OnValChange(val);
console.log("after");
}, [val]);
return (
<button onClick={() => setVal(val + 1)}>Count</button>
)
}
测试:
it("Sends val to parent when button is clicked", () => {
const prop = {
OnValChange: jest.fn();
}
const control = mount(<MyComp {...prop} />);
expect(prop.OnValChange).toHaveBeenCalledTimes(0);
control.find(button).simulate("click");
expect(prop.OnValChange).toHaveBeenCalledTimes(1);
})
答案 0 :(得分:0)
要回答您的问题,功能组件中没有“ this”。
但是将道具传递给父母也不是“反应的方式”。
对于此用例,我建议使用Context和Reducers设置全局状态/存储。然后,您可以将任何组件中的任何数据发送到商店中,并在应用程序中的任何位置访问该商店。
以下示例用于打开和关闭抽屉菜单,但是您可以添加任何大小写和任何数据
示例:
import React, { createContext, useReducer } from "react"
const reducer = (state, action) => {
switch (action.type) {
case "OPEN_MENU":
// spread current state and then override the one part of the state you want to update
return { ...state, menuState: true }
case "CLOSE_MENU":
return { ...state, menuState: false }
case "TOGGLE_MENU":
return { ...state, menuState: !state.menuState }
default:
return
}
}
const initialState = { menuState: false }
const AppContext = createContext(initialState)
const AppProvider = props => {
const [state, dispatch] = useReducer(reducer, initialState)
return (
<AppContext.Provider value={{ state, dispatch }}>
{props.children}
</AppContext.Provider>
)
}
export { AppContext, AppProvider }
然后,您只需要将应用程序包装在AppProvider中即可。 (或您命名提供商的任何名称。“ ContextProvider”,“ StateProvider”等。)
设置好商店,Reducer和提供者后,您可以从任何此类组件更新上下文。
import React from 'react'
import { AppContext } from "../../context/Context"
const MyComponent = () => {
const { state, dispatch } = useContext(AppContext)
console.log('state: ', state); // access your state from anywhere
return (
<div>
{/* Update your state from anywhere */}
<button onClick={() => dispatch({ type: "TOGGLE_MENU" })}>Click me to update your context!</button>
</div>
)
}
该示例非常适合简单的事情,但是如果您想在调度中传递值,则可以像这样设置开关
const reducer = (state, action) => {
const { payload } = action
switch (action.type) {
case "SET_SOME_VALUE":
return { ...state, someValue: payload }
default:
return
}
}
,然后在调用调度时,可以像这样设置有效负载值
dispatch({ type: "SET_SOME_VALUE", payload: myVariable })
有关上下文的更多信息,请参见:https://reactjs.org/docs/context.html
答案 1 :(得分:0)
useEffect
在组件首次安装时将始终被调用一次,而在您触发按钮单击时将被第二次调用,因此正确的测试应像这样
it("Sends val to parent when button is clicked", () => {
const prop = {
OnValChange: jest.fn();
}
const control = mount(<MyComp {...prop} />);
expect(prop.OnValChange).toHaveBeenCalledTimes(1);
control.find(button).simulate("click");
expect(prop.OnValChange).toHaveBeenCalledTimes(2);
})
如果您始终是0次,我怀疑这是enzyme-adapter-react-16
版本的问题。当我将版本切换到1.13.0
时,将会遇到与您相同的问题,您可以尝试将enzyme -adapter-react-16
更新为最新版本。