I am using i18n so that my app is multilingual. This seems to work fine, except for when I'm testing the app.
I render a component named ProjectNavigation in my test. This component uses the useTranslation hook to translate some words in my project navbar.
import React from 'react';
import {
render,
screen,
} from '#testing-library/react';
import ProjectNavigation from '../pages/ProjectNavigation';
test('Checks to see if project navigation is rendered', () => {
render(
<React.Suspense fallback="Loading...">
<ProjectNavigation useSuspense={false} />
</React.Suspense>,
);
expect(screen.getByRole('navigation')).toBeVisible();
});
When I render with suspense, the only thing that loads is the fallback, which is currently set to "Loading...".
I've tried useSuspense={false} when rendering, but the test will not run and I receive this error:
ProjectNavigation suspended while rendering, but no fallback UI was specified.
Add a <Suspense fallback=...> component higher in the tree to provide a loading indicator or placeholder to display.
It seems the component is not able to render, and this is why it only shows the fallback.
Anyone know how to deal with the component not being able to render?
Related
UPDATE
After reviewing more of my tests I have found this behavior to be inconsistent. I have very similar tests and some render and perform as expected after the update, but others return the empty div. Does anyone have any insight on what the issue may be?
Recently at work I updated our ui from using React v16 to v18. I also updated the dev dependencies as recommended. Some of my tests are working just fine, specifically ones that test routes and functionality after the element is rendered based on a route. Imports are the same in both test scenarios.
// Sample Component
import React, {useState} from "react";
import Modal from "react-bootstrap/Modal";
import Button from "react-bootstrap/Button";
export default function MyModal({
show,
message
}) {
if (!show) {
return null;
}
const [visible, setVisible] = useState(true);
return (
<Modal
show={visible}
data-testid={"myComponent-modal"}
>
<Modal.Body>
{message}
</Modal.Body>
<Modal.Footer>
<Button>Ok</Button>
</Modal.Footer>
</Modal
);
}
Testing some route that eventually will show MyModal component after some simulated actions.
// Test details
const {getByRole} = render(
<MemoryRouter initialEntries={["/somePath"]}>
<UserContext.Provider value={value}>
<Routes>
<Route
path="/somePath"
element={<MyComponent {...props} />}
/>
</Routes>
</UserContext.Provider>
</MemoryRouter>
);
// fill in some form detail, then click submit button, then myModal appears
// Result is everything renders as I expect and test passes.
Other tests, specifically ones where I am just trying to render a component, are just returning an empty div to me from the render function.
// Test Details
// This is an MRE not my actual test as I can't that code
import "#testing-library/jest-dom"
import React from "react";
import MyModal from "../../components/MyModal";
import { render, screen } from "#testing-library/react";
const {queryByText} = render(
<MyModal show={true} message={"Test Message"} />
);
screen.debug();
const modalMessage = queryByText("Test Message");
expect(modalMessage).toBeInTheDocument();
// Result: assertion fails
// screen.debug() returns <body><div /></body>
Dev Dependencies
#testing-library/dom: "^8.5.0"
#testing-library/jest-dom: "^5.11.10"
#testing-library/react: "^13.4.0"
#testing-library/react-hooks: "^7.0.2"
#testing-library/user-event: "^13.5.0"
react-test-renderer: "^18.2.0"
react-testing-library: "^7.0.1"
jest: "^26.6.3"
jest-cli: "^26.6.3"
jest-junit: "^6.2.1"
jest-mock-axios: "^4.2.1"
jsdom: "11.9.0"
We have several other dev dependencies, but none that I believe would be affecting these tests.
I have tried changing dev dependency versions, as not all have been updated to latest, but that didn't seem to work. I have downgraded them all back, but that seems to run the tests in react v17 not 18 which isn't desired.
I've tried debugging, but am struggling there. When it reaches the line to render the component it seems to jump up to the test signature and not into my component where I have break points then eventually back down to the test, but at that point it's already an empty div element.
I've tried looking through blogs other posts, but am either not finding any solution or have found other posts with my same issue where no answers have been provided.
I've also tried waiting after the render, but that didn't seem to help.
I tried wrapping the component within a MemoryRouter.
It just seems as though render is not even trying to render my component.
Any assistance would be greatly appreciated. As frustrating as this has been to resolve I am still loving the developer life. Happy coding to everyone!!!
I've been trying to work with next.js right now and when I imported a navbar component to my _app.tsx and run the project, it would give me an error of saying "Cannot use import statement outside a module." This doesn't occur on vanilla React though.
What I did is I made a Navbar component in components folder.
navbar.tsx
//some imports on react-bootstrap
function NavigationBar(): JSX:Element {
<>
//Navbar code
</>
on my _app.tsx, I imported the Navbar so that it would be accessible to all pages of the app.
_app.tsx
import type { AppProps } from 'next/app'
import NavigationBar from "../components/navbar.tsx"
function MyApp({ Component, pageProps }: AppProps) {
return (
<>
<NavigationBar/>
<Component {...pageProps} />
</>
)
}
It didn't highlight any error until I tried to run the project.
The error seems to occur in the bootstrap folder in node_modules though.
Attached is the error log on the console.
Thanks in advance.
Try adding
type: "module"
To your package.json
SOLVED:
I dabbled with the import statement and this works depending on how you import the react-bootstrap component.
//this doesn't work
import Navbar from "react-bootstrap/esm/Navbar"
//this works
import {Navbar} from "react-bootstrap"
//this works
import Navbar from "react-bootstrap/Navbar"
It's my mistake importing it from the esm file directly.
We use Reakit dialogs to prompt users to take an action in our React web app.
On some pages, we have specific text related to the action and would like to render this specific content in the dialog. On all other pages, we want to fall back to generic text.
Our simplified component hierarchy for generic pages looks like:
<BaseLayout>
...
</BaseLayout>
and for a page where we want to show specific text,
<BaseLayout>
...
<SpecificPage/>
...
</BaseLayout>
What we'd like to happen is:
On pages that render the SpecificPage component, the Dialog appears with the specific text
On pages that do not render the SpecificPage component, the Dialog appears with the fallback generic text
Our approach was to have the SpecificPage component render a Dialog with the page-specific text, and the BaseLayout component render a Dialog with the generic fallback text, but this approach isn't ideal -- users see a flash of the BaseLayout dialog before the SpecificPage dialog is rendered. Is there any way to define a single component that is "overridden" by descendants in the component hierarchy, or other way to achieve this conditional rendering?
You can simply check if you're rendering anything as children in the BaseLayout component or not, If not you can fallback to generic text.
Here's an example.
App Component
import React from 'react';
import { BaseLayout } from './BaseLayout';
export function App(props) {
return (
<div className='App'>
<BaseLayout>
<h1>Hello World.</h1>
</BaseLayout>. // Renders hello world
<BaseLayout /> // Render generic text
</div>
);
}
Base Layout Component
import React from 'react';
export function BaseLayout({children}) {
return (
<div>
{children ? children : "Some Generic Text"}
</div>
);
}
See https://github.com/ariakit/ariakit/discussions/1266#discussioncomment-2617748 for a solution and CodeSandbox that solves this problem well using the Constate library.
I am trying Reactjs for the first time, but when want to render something, it only renders it when I restart my project. If I hit save, nothing happens. Have someone met with this problem yet?
import React from 'react';
function App(){
return (
<div>
<h1>Hello React</h1>
<button>Button</button>
</div>
);
}
export default App;
import React from 'react';
import ReactDOM from 'react-dom';
ReactDOM.render(<App />, document.getElementById('root'));
If you want the app to render the latest changes you made to the source files, you have to implement hot-reloading.
Check this site for more info : https://gaearon.github.io/react-hot-loader/getstarted/
It will scan changes you do to the source files and automatically apply the changes to the running app. It will also make sure that the state of the app is not lost during this change.
I've was testing the react-sketchapp which looks pretty neat so far.
Besides rendering the default sketch elements like Text,View,Image and so on, would it be possible to render a default react component containing HTML-Markup styled with scss?
I tried rendering the following Hello-Component:
import React from 'react';
import { render, Artboard, Text, View } from 'react-sketchapp';
const Hello = () => (
<View
name={`Hello View`}
>
<Text name="Hello Text">
<span>Hello World</span>
</Text>
</View>
);
const Document = () => (
<Artboard
name="Hello Board"
>
<Hello />
</Artboard>
);
export default (context) => {
render(<Document />, context.document.currentPage());
}
but I get the following error:
Could not find renderer for type 'span' flexToSketchJSON
Is rendering default react components including html / css to Sketch possible?
You can't render HTML elements to Sketch, same as you can't render HTML elements to React Native.
React is just a way of managing a tree of abstract components. How to render these components needs to be defined by the specific renderer you are using. react-sketchapp is a renderer that understands components which render to Sketch elements, but it does not understand HTML elements such as div. (and React Native includes a renderer which knows how to render React Native components to native mobile views, react-music is a renderer which knows how to render React Music components into audio, and so forth).
React, in and of itself, has nothing to do with HTML elements or the DOM. The react-dom renderer library is where the magic of rendering into the DOM happens. If you want to render HTML elements to Sketch, you'll need to write a React renderer which knows how to convert HTML elements to Sketch's file format.
You can export any HTML/CSS to Sketch using html-sketchapp.
It is possible.
Try looking into using React-Primitives with React-SketchApp.
https://github.com/lelandrichardson/react-primitives
It's in a few examples within React-SketchApp e.g.
https://github.com/airbnb/react-sketchapp/tree/master/examples/profile-cards-primitives