I've been fighting this for a few days now and I can't get the righ way of doing what I need.
Basically I have a context that provides a theme fetched from an API. The context has the values of theme, loading, and functions to fetch and update the loading state. It looks like so:
import React, { useState } from "react";
import ThemeService from "../services/GetThemes";
const AvailableThemesContext = React.createContext();
const { Provider, Consumer } = AvailableThemesContext;
const ThemesProvider = ({ children }) => {
const [contextTheme, setTheme] = useState({});
const [loading, setLoading] = useState(true);
function handleData(data) {
setTheme(data);
setLoading(false);
}
function fetchThemes() {
setLoading(true);
new ThemeService().getData(handleData);
}
function refresh(data) {
setTheme(data);
}
return (
<Provider value={{ contextTheme, fetchThemes, refresh, setLoading, }}>
{children}
</Provider>
);
};
export { ThemesProvider, Consumer as ThemeConsumer, AvailableThemesContext };
This is how I provide said context to the App in the index.js file:
import { ThemesProvider } from "./context/ThemeProvider";
ReactDOM.render(
<ThemesProvider value={{}}>
<App />
</ThemesProvider>,
document.getElementById("root")
);
In the child component, there is a useEffect
that looks at the loading
state to render a spinner or some other stuff. As default renders the spinner. Then I try to change the state of loading
to false
but I can't manage to do so.
Here is my test:
import React from "react";
// import { render } from "@testing-library/react";
import { render, screen } from "./test-utils";
import CalendarView from "../views/CalendarView";
import AvailableThemesContext from "../context/ThemeProvider";
const { loading } = AvailableThemesContext;
describe("<CalendarView />", () => {
test("It renders without crashing", async () => {
const { getByLabelText } = render(<CalendarView />);
expect(getByLabelText("audio-loading")).toBeInTheDocument();
// ---> This looks for the loader ands resolves OK
});
test("It renders without crashing", () => {
const renderComponent = render(
<ThemeProvider value={{ loading: false}}>
<CalendarView />);
</ThemesProvider>
expect(renderComponent.getByTestId("picker-component")).toBeInTheDocument();
});
});
For more that I try to inject the new state the component never sees the change.
Help please?