So I am currently developing a web application and noticed that some of my components renders twice and I am not really sure why and also that console.log appears twice in the console. I am sure that I am only calling the console.log once and the toast once.
I have read about the strict mode in reactjs but I am unsure if it is enabled or not since I can't find it in my source code.
Here's my app.jsx
import '../css/bootstrap/bootstrap.min.css';
import '../css/bootstrap-icons-1.10.3/bootstrap-icons.css'
import '../css/dhca-base.sass'
import React from 'react';
import { createInertiaApp } from '#inertiajs/react'
import { createRoot } from 'react-dom/client'
const appName = window.document.getElementsByTagName('title')[0]?.innerText || 'Laravel';
createInertiaApp({
title: (title) => `${title} - ${appName}`,
resolve: name => {
const pages = import.meta.glob('./Pages/**/*.jsx', { eager: true })
return pages[`./Pages/${name}.jsx`]
},
setup({ el, App, props }) {
createRoot(el).render(<App {...props} />)
},
})
I also have the reactjs development extensions in my browser and it shows me a warning sign near the Inertia title.
Turns out everything is set up correctly and I was just not using the useEffect hook correctly.
Related
How do I get route propagation working in a Nextjs Shopify app?
I'm building a Shopify App scaffolded with the CLI and have issues with routing using the Nextjs router. The standard embedded app implementation does not update the URL so a RoutePropagator component is needed.
I implemented Shopify's RoutePropagator but got the error TypeError: Cannot read properties of undefined (reading 'pathname')
Then I found this implementation which works for updating the URL, but runs into a really strange issue for Dynamic Urls.
Whenever a user navigated to a dynamic url, the url would update with [id] in the url. Gif example:
Narrowing it down, the below snipped causes the above dynamic url issue:
import { useEffect, useContext } from "react";
import Router, { useRouter } from "next/router";
import { Context as AppBridgeContext } from "#shopify/app-bridge-react";
import { Redirect } from "#shopify/app-bridge/actions";
import { RoutePropagator as ShopifyRoutePropagator } from "#shopify/app-bridge-react";
const RoutePropagator = () => {
const router = useRouter();
const { route } = router;
const appBridge = React.useContext(AppBridgeContext);
// Subscribe to appBridge changes - captures appBridge urls
// and sends them to Next.js router. Use useEffect hook to
// load once when component mounted
useEffect(() => {
appBridge.subscribe(Redirect.Action.APP, ({ path }) => {
Router.push(path);
});
}, []);
return appBridge && route ? (
<ShopifyRoutePropagator location={route} app={appBridge} />
) : null;
};
export default RoutePropagator;
How do I get the URL to update as the user navigates through the application for all urls (including dynamic urls)?
Use
const { asPath } = router
instead of route and it's gonna work!
We have a React Native app, and have trouble in Jest testing this:
import React from 'react';
import { render } from '#testing-library/react-native';
import MyScreen from '../../../../../src/screens/MyScreen/index';
import Provider from '../../../../__helpers__/Provider';
import { t } from 'core/utils';
import '#testing-library/jest-dom';
jest.mock('#react-navigation/native', () => {
return {
...jest.requireActual('#react-navigation/native'),
useNavigation: () => ({
navigate: jest.fn(),
}),
};
});
jest.mock('#react-navigation/core', () => {
return {
...jest.requireActual('#react-navigation/core'),
useFocusEffect: () => ({
navigate: jest.fn(),
}),
};
});
describe('<AddEditSchedulable />', () => {
it('tests a button is disabled', () => {
const myProperty = {
myData: 'myData'
};
const myRender = render(
Provider(() => <MyScreen myProperty={myProperty} />),
);
const button = myRender.getByText(t('common.buttons.save')); // Returns a complex "_fiber" object.
expect(button).toBeDisabled(); // Expects an HTML element.
});
});
The button returned by getByText contains an object we dont understand containing lots of "_fiber" objects. From this I think we need to get HTML elements to correctly use the toBeDisabled function, but this is React Native and I dont think it uses HTML elements under the hood.
So can we either, get HTML elements from React Native, or can we get functions that understand React Native elements that have the functionality we need (at least accessing properties, ie "disabled")?
We are in circles because standard React seems very different to React Native in Jest tests.
The library #testing-library/jest-dom is meant only for #testing-library/react. Since you are using React Native, the custom matcher toBeDisabled() doesn't understand the element. The import for react native is below.
import '#testing-library/jest-native/extend-expect';
Remove the import and remove it from the project.
import '#testing-library/jest-dom';
Also, please make sure this returns a react native component.
Provider(() => <MyScreen myProperty={myProperty} />),
I wrote my project in react and now I want to add it to Laravel using inertia.js but I can't access context since I'm using dynamic-import for code splitting.
I'm wondering if there is a way to access context in this situation.
This is my app.js code:
import React from 'react'
import { render } from 'react-dom'
import { createInertiaApp } from '#inertiajs/inertia-react'
createInertiaApp({
resolve: name => require(./src/screens/${name}),
setup({ el, App, props }) {
render(<App {...props} />, el)
},
})
I want to write stories for both React and Svelte components. I already have a few React components, and I'm attempting to install Svelte. My closest attempt can either run React OR Svelte depending on whether I comment out my React configuration. If I don't comment it out, I get this message when I look at my Svelte component in storybook:
Error: Objects are not valid as a React child (found: object with keys {Component}). If you meant to render a collection of children, use an array instead.
in unboundStoryFn
in ErrorBoundary
(further stack trace)
This refers to my story stories/test.svelte-stories.js:
import { storiesOf } from '#storybook/svelte';
import TestSvelteComponent from '../src/testComponentGroup/TestSvelteComponent.svelte';
storiesOf('TestSvelteComponent', module)
.add('Svelte Test', () => ({
Component: TestSvelteComponent
}));
My configuration is as follows:
.storybook/config.js:
import './config.react'; // If I comment out this line, I can make the svelte component work in storybook, but of course my react stories won't appear.
import './config.svelte';
.storybook/config.react.js:
import { configure } from '#storybook/react';
const req = require.context('../stories', true, /\.react-stories\.js$/);
function loadStories() {
req.keys().forEach(filename => req(filename));
}
configure(loadStories, module);
.storybook/config.svelte.js:
import { configure } from '#storybook/svelte';
const req = require.context('../stories', true, /\.svelte-stories\.js$/);
function loadStories() {
req.keys().forEach(filename => req(filename));
}
configure(loadStories, module);
.storybook/webpack.config.js:
module.exports = async ({ config, mode }) => {
let j;
// Find svelteloader from the webpack config
const svelteloader = config.module.rules.find((r, i) => {
if (r.loader && r.loader.includes('svelte-loader')) {
j = i;
return true;
}
});
// safely inject preprocess into the config
config.module.rules[j] = {
...svelteloader,
options: {
...svelteloader.options,
}
}
// return the overridden config
return config;
}
src/testComponentGroup/TestSvelteComponent.svelte:
<h1>
Hello
</h1>
It seems as though it's attempting to parse JSX via the Svelte test files, but if I import both React AND Svelte configurations I can still see the React components behaving properly.
See this discussion on github : https://github.com/storybookjs/storybook/issues/3889
It's not possible now and it's planned for the v7.0
The official position now is to create two sets of configuration (preview and manager), instanciate two separates storybook, and then use composition to assemble the two storybook into one.
im brand new to Next.js and i have the following situation. i want to redirect the user to the route /messages if he type route /messages/123 based on css media query so if he is mobile we will not redirect and if he in browser then redirect .
i have tried the following code
import React, { useLayoutEffect } from 'react';
import { useRouter, push } from 'next/router';
import useMediaQuery from '#material-ui/core/useMediaQuery';
import Layout from '../components/Customer/Layout/Layout';
import Chat from '../components/Customer/Chat/Chat';
const Messages = () => {
const { pathname, push } = useRouter();
const matches = useMediaQuery('(min-width:1024px)');
useLayoutEffect(() => {
console.log('I am about to render!');
if (matches && pathname === '/messages') {
console.log('match!');
push('/');
}
}, [matches, pathname, push]);
return (
<Layout currentURL={pathname}>
<Chat />
</Layout>
);
};
export default Messages;
the problem is the component render twice before redirect
But You should probably be using useEffect since you are not trying to do any DOM manipulations or calculations.
useLayoutEffect: If you need to mutate the DOM and/or DO need to perform measurements
useEffect: If you don't need to interact with the DOM at all or your DOM changes are unobservable (seriously, most of the time you should use this).
You should see immediate action.
Edit:
You can use Next JS getInitialProps to check the request headers and determine if the request if from mobile or desktop then redirect from there.
getInitialProps({ res, req }) {
if (res) {
// Test req.headers['user-agent'] to see if its mobile or not then redirect accordingly
res.writeHead(302, {
Location: '/message'
})
res.end()
}
return {}
}