我是 React Hooks 的新手,我想要实现的是测试一个 React 组件(称为 CardFooter),该组件包含对 useEffect 钩子的调用,该钩子被触发并修改了全局上下文变量。
CardFooter.js:
const CardFooter = props => {
const [localState, setLocalState] = useState({
attachmentError: false
});
const globalContext = useContext(GlobalContext);
React.useEffect(()=> {
setLocalState({
...localState,
attachmentError: globalContext.data.attachmentError
});
},[globalContext.data.attachmentError]);
}
Run Code Online (Sandbox Code Playgroud)
CardFooter.test.js:
import Enzyme, { shallow } from 'enzyme';
Enzyme.configure({ adapter: new Adapter() });
describe('<CardFooter />', () => {
let useEffect;
const mockUseEffect = () => {
useEffect.mockImplementation(f => f());
};
useEffect = jest.spyOn(React, "useEffect");
mockUseEffect(); //
it('should render correctly with no props.', () …Run Code Online (Sandbox Code Playgroud) 基本场景是这样的:我有一个width: 100%在样式表中定义的组件。因此它应该保留其父组件的宽度。我想计算我的组件的宽度并将其应用于我的子组件,因为我通过渲染它createPortal并且我希望它们具有相同的宽度。这在浏览器中有效。但是,在我的测试中,我发现它window.getComputedStyle(component)没有返回任何从样式表应用的样式。
正如建议的那样,我可以模拟 javascript 窗口,但这实际上与我希望做的事情背道而驰,我认为。我想验证浏览器中存在的行为,该行为window.getComputedStyle()返回应用的所有样式,而不仅仅是内联样式。
我把一个简单的例子放到了一个代码盒中:https ://codesandbox.io/s/goofy-wilson-6v4dp
也在这里:
function App() {
return (
<div className="App">
<WidthComponent />
</div>
)
}
function WidthComponent() {
const myInput = useRef();
const [inputWidth, setInputWidth] = useState(0);
useEffect(() => {
console.log("in handleLoad");
const width = myInput.current ? myInput.current.offsetWidth : 0;
setInputWidth(width);
}, [myInput]);
return (
<div className="inherited-width" ref={myInput}>
<div style={{ width: inputWidth }} className="child-element">
Hello
</div>
</div>
);
}
// test
test("width is inherited", () => …Run Code Online (Sandbox Code Playgroud)reactjs jestjs react-testing-library react-portal use-effect
我有一个getUrl()调用 API 端点的方法
useEffect(() => {
getUrl()
.then(x => x.json())
.then(x => {
const { result } = x;
});
});
Run Code Online (Sandbox Code Playgroud)
我可以在控制台中看到我页面中的调用,正如您在屏幕截图中看到的,这是我的数据
{
"result":"https://www.google.it",
"error":null,
"errorCode":null,
"isSuccessful":true,
"operationStatusCode":"OK"
}
Run Code Online (Sandbox Code Playgroud)
如何在我的视图中在外部链接中显示以下result链接示例https://www.gooole.it?
我必须使用状态吗?
我需要一个如何编码的例子在这里
<a target="_blank" href={result}>Google Link</a>
Run Code Online (Sandbox Code Playgroud)
我正在学习 React(带钩子),想问一下我们进行的每个 API 调用是否都必须在 useEffect 钩子内?
在我的测试应用程序中,我有一个如下的工作模式:我设置状态,然后单击按钮后,我运行一个函数,向我的 API 发送 get 请求,并在 .then 块中将接收到的数据附加到状态。
我还有一个 useEffect 挂钩,仅在所述状态发生变化时运行(使用带有状态值的依赖数组),并且它使用前一个状态中的新数据设置另一个状态。第二个状态是我的应用程序在渲染块中渲染的状态。
这样,我的数据获取实际上发生在单击按钮时运行的函数中,而不是在 useEffect 本身中。似乎正在发挥作用。
这是一个有效的模式吗?提前致谢!
编辑:例如,这是单击按钮时运行的函数
const addClock = timezone => {
let duplicate = false;
selectedTimezones.forEach(item => {
if (item.timezone === timezone) {
alert("Timezone already selected");
duplicate = true;
return;
}
});
if (duplicate) {
return;
}
let currentURL = `http://worldtimeapi.org/api/timezone/${timezone}`;
fetch(currentURL)
.then(blob=>blob.json())
.then(data => {
setSelectedTimezones(prevState => [...prevState, data]);
}
);
}
Run Code Online (Sandbox Code Playgroud) 我不明白为什么我的useEffect()React 函数无法访问我的组件的状态变量。当用户放弃在我们的应用程序中创建列表并导航到另一个页面时,我试图创建一个日志。我正在使用useEffect() return复制componentWillUnmount()生命周期方法的方法。你能帮我吗?
let[progress, setProgress] = React.useState(0)
... user starts building their listing, causing progress to increment ...
console.log(`progress outside useEffect: ${progress}`)
useEffect(() => {
return () => logAbandonListing()
}, [])
const logAbandonListing = () => {
console.log(`progress inside: ${progress}`)
if (progress > 0) {
addToLog(userId)
}
}
Run Code Online (Sandbox Code Playgroud)
代码将达到addToLog(),导致记录此行为。
这就是当用户在他们的列表中输入一些内容,导致progress增加,然后离开页面时发生的情况。
useEffect()方法完美运行,并触发该logAbandonListing()功能console.log()(上面useEffect)记录了大于 0 的progress状态console.log()用于日志0 …希望有人能指出我正确的方向。基本上我已经创建了一个使用钩子的反应应用程序,特别是 useContext、useEffect 和 useReducer。我的问题是我似乎无法通过测试来检测相关组件的点击或调度事件。
可以在以下位置找到我的应用程序的精简版本:https : //github.com/atlantisstorm/hooks-testing 测试与 layout.test.js 脚本相关。
我尝试了各种方法,模拟分派、useContext 等的不同方法,但对此并不满意。最新版本。
布局.test.js
import React from 'react';
import { render, fireEvent } from "@testing-library/react";
import Layout from './layout';
import App from './app';
import { Provider, initialState } from './context';
const dispatch = jest.fn();
const spy = jest
.spyOn(React, 'useContext')
.mockImplementation(() => ({
state: initialState,
dispatch: dispatch
}));
describe('Layout component', () => {
it('starts with a count of 0', () => {
const { getByTestId } = render(
<App>
<Provider> …Run Code Online (Sandbox Code Playgroud) 在我的测试中,组件接收其 props 并设置组件。
这会触发 useEffect 发出 http 请求(我模拟)。
返回获取的模拟 resp 数据,但 useEffect 内的清理函数已被调用(因此组件已卸载),因此我收到所有这些错误。
如何防止组件卸载以便更新状态?我尝试过采取行动,没有采取行动,没有任何原因导致组件等待获取完成。
我应该说我的警告只是警告,但我不喜欢所有的红色,它表明出了问题。
export const BalanceModule = (props) => {
const [report, setReport] = useState();
useEffect(() => {
fetch('http://.....').then((resp) => {
console.log("data returned!!!")
setReports((report) => {
return {...report, data: resp}
})
})
return () => {
console.log("unmounted!!!")
};
}, [report])
.... trigger update on report here
}
// the test:
test("simplified-version", async () => {
act(() => {
render(
<BalanceModule {...reportConfig}></BalanceModule>
);
});
await screen.findByText("2021-01-20T01:04:38");
expect(screen.getByText("2021-01-20T01:04:38")).toBeTruthy();
});
Run Code Online (Sandbox Code Playgroud) 我有一个疑问..我可以在 getStaticProps 中使用 useEffect 吗?
我正在尝试在 getStaticProps 中运行一个函数...它有效..但我不知道这是否是推荐的做法。
useEffect(() => {
remarkBody()
}, [body, blogPostCollection])
Run Code Online (Sandbox Code Playgroud)
如果没有......运行它的最佳方式是什么?
在 useEffect 中使用 IIFE 是个好习惯还是我应该声明 async 函数然后调用它?
useEffect(() => {
(async () => {
const response = await fetch(
"https://jsonplaceholder.typicode.com/posts"
);
const json = await response.json();
setPosts(json);
})();
});
Run Code Online (Sandbox Code Playgroud) 在我们的反应应用程序中,我们有父子组件。子组件调用父方法来更新父状态值。这是示例代码
//父组件
const parent = ({ items }) => {
const [information, setInformation] = useState([]);
const updateParentInformation = (childUpdate) => {
setInformation(information + childUpdates)
}
return (
<div>
<div>{information}</div>
...
{items.map((item) => {
return (
<ChildComponent item={item} updateParentInformation={updateParentInformation} />
)})}
</div>
)
}
Run Code Online (Sandbox Code Playgroud)
//子组件
const ChildComponent = ({ item, updateParentInformation }) => {
useEffect(() => {
const cardInformation = calculateCardInformation(item)
updateParentInformation(cardAmpScripts)
}, [item])
return (
<div>
.....
</div>
)
}
Run Code Online (Sandbox Code Playgroud)
因此子组件调用父组件的 updateParentInformation 函数来更新父组件的状态,从而重新渲染父组件。我在这里有几个问题
在某些情况下,我们可能有100-150个子组件,在这种情况下我们的父母会重新渲染很多,如何避免这种情况。我们可以通过这段代码来避免这种情况
....
let recievedUpdates = 0
const …Run Code Online (Sandbox Code Playgroud)use-effect ×10
reactjs ×9
react-hooks ×6
javascript ×3
jestjs ×2
next.js ×2
api ×1
dispatch ×1
iife ×1
react-portal ×1
use-context ×1
use-ref ×1
use-state ×1