Accessing context API when using inertia.js and code splitting - reactjs

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)
},
})

Related

Laravel + InertiaJS + ReactJS Components Renders Twice

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.

React Native Jest testing

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} />),

Testing in React Redux

I have Dashboard component like below.
import React, { Component } from 'react';
import DataTable from './DataTable';
import { connect } from 'react-redux';
class Dashboard extends Component {
render() {
return <DataTable />;
}
}
export default connect()(Dashboard);
My test is like below
App.test.js
import React from 'react';
import ReactDOM from 'react-dom';
import Dashboard from './components/Dashboard';
it('renders without crashing', () => {
const div = document.createElement('div');
ReactDOM.render(<Dashboard />, div);
ReactDOM.unmountComponentAtNode(div);
});
describe('Addition', () => {
it('knows that 2 and 2 make 4', () => {
expect(2 + 2).toBe(4);
});
});
I am trying to run test using this command npm test App.test.js.
I am getting below error
Invariant Violation: Could not find "store" in the context of "Connect(Dashboard)". Either wrap the root component in a <Provider>, or pass a custom React context provider to <Provider> and the corresponding React context consumer to Connect(Dashboard) in connect options.
Your Dashboard is connected to redux, which requires a store. You have a two possibilities :
use Enzyme and redux-mock-store in order to configure a store used when you're mounting your component. This is not well maintainable and leads to a strong dependency between Component and store.
export the non-connected Dashboard (in addition to the default export connected), and mount (eventually with the required props). This is much simpler and maintainable.
export class Dashboard extends Component {
render() {
return <DataTable />;
}
}
// Test :
import { Dashboard } from './components/Dashboard';
ReactDOM.render(<Dashboard />, div);
Note: I think you simplified your connect() for the example purpose, because it does not do anything here, but if this is your real implementation you could drop the connect part and still use the default export for your test.

Can we integrate react component into Aurelia project?

I have created one react component and build it using webpack and deployed on server. I want to integrate this component into Aurelia Project.
I tried using below npm module:
https://www.npmjs.com/package/aurelia-react-loader
In above module mentioned, component name need pass into html file. like in example my-react-component.js is passing into html file.
But my React Component is loading into root in html tag using below code:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render((
<App/>
), document.getElementById('root'));
and after running webpack module, it is creating one JavaScript file that is called index_bundle.js file. Here imported App module is main js component. It is rendering into index.html on root element via ReactDOM.
So I am not sure, How I am going to integrate React component link or url into Aurelia application?
Please let me know if you have any doubts in question. I can do explain in detail.
Thanks in advance.
Harish
Yeah, it's really easy to integrate a react component in to an Aurelia app. Check out my project where I do just that here: https://github.com/ashleygrant/aurelia-loves-react
I'm not even using the loader plugin you mentioned.
Here's how to wrap a third-party react component in an Aurelia custom element:
import React from 'react';
import ReactDOM from 'react-dom';
import ReactDatePicker from 'react-datepicker';
import { noView, bindable, inject } from 'aurelia-framework';
#noView(['react-datepicker/react-datepicker.css'])
#inject(Element)
export class DatePicker {
#bindable selectedDate;
#bindable onChange;
constructor(element) {
this.element = element;
}
selectedDateChanged() {
this.render();
}
render() {
ReactDOM.render(
<ReactDatePicker
selected={this.selectedDate}
onChange={date => this.onChange({ date: date })}
/>,
this.element
);
}
// How to use native DOM events to pass the changed date
/*render() {
ReactDOM.render(
<ReactDatePicker
selected={this.selectedDate}
onChange={date => {
let event = new CustomEvent('change', { 'detail': date });
// Dispatch the event.
this.element.dispatchEvent(event);
}
}
/>,
this.element
);
}*/
}
And here's how to do it while using a custom react component that is part of the Aurelia project:
import React from 'react';
import ReactDOM from 'react-dom';
import { noView, bindable, inject } from 'aurelia-framework';
import FormattedDate from '../react-components/formatted-date';
#noView()
#inject(Element)
export class ReactDate {
#bindable date;
#bindable format = 'dddd, MMMM D, YYYY';
constructor(element) {
this.element = element;
}
dateChanged() {
this.render();
}
formatChanged() {
this.render();
}
render() {
ReactDOM.render(
<FormattedDate
date={this.date}
format={this.format}
/>,
this.element
);
}
}
As you can see, it's pretty simple. I like doing it by hand rather than using the loader as I can set up databinding for each property so it works in a more "Aurelia-ey" way.

Invariant Violation: The root route must render a single element error in react-router 2 dynamic routing

I have simple Hello World App with one route no child route or index route. For routing i using plain routes instead of jsx sysntax. Again i am using react-router's dynamic routing to load Hello component with webpack.
My app.jsx file has the following code.
import React from "react";
import ReactDOM from "react-dom";
import {Router, browserHistory} from "react-router";
import Hello from "./components/Hello";
const routes = [{
path:"/",
getComponents(location, callback) {
require.ensure([], function (require) {
callback(null, require('./components/Hello'))
})
}
}];
ReactDOM.render(
<Router history={browserHistory} routes={routes}/>,
document.getElementById("container")
);
Hello.jsx component has the following code
import React from "react";
export default class Hello extends React.Component {
render() {
return (
<h2>Hello World</h2>
)
}
}
This error happens because webpack doesn't support es6 modules
if you are using babel to transpile es6 code then use the default keyword like
require('./components/Hello').default
so the routes will be
const routes = [{
path:"/",
getComponents(location, callback) {
require.ensure([], function (require) {
callback(null, require('./components/Hello').default)
})
}
}];

Resources