Violation 'requestIdleCallbackHandler ' took ms - reactjs

I'm writing an app generated with create-react-app with redux, react-redux, and react-router. Whenever I click a Link like this:
import React from 'react'
import { Link } from 'react-router'
import ThingCard from '../../components/ThingCard'
const ThingsList = ({things}) => {
return (
<ul>
{things.map(thing =>
<Link to={"/things/"+thing.id} key={thing.id}><ThingCard thing={thing}/></Link>
)}
</ul>
)
}
export default ThingsList
I see the following warnings in my console. I have no idea where they come from or what they mean. Google search didn't yield any useful results. Can these warnings be safely ignored, if not how can I find out more about them? I believe this issue is preventing the parent page from rendering it's children.
I've disabled all network requests.
EDIT: This error only shows up in Chrome Canary and not Google Chrome. However, Google Chrome is not rendering the children properly (potentially due to this issue)

It can be safely ignored. Here is good explanation why do you see this.
The reason you see requestIdleCallback here is most probably because you are using React 16+ which has a totally new architecture Fiber You can read more about it
TL;DR; It just notifies you that some of your/their code took longer than 16ms, thus you may not always get 60fp.

Related

Block editor giving invalid hook call error

I am trying to get the wordpress block editor to load in a react project: https://www.npmjs.com/package/#wordpress/block-editor.
I have set it up exactly as per the example on the npm page but it gives an invalid hook error. I think perhaps it is due to a version mismatch as error suggest?
This is the code:
import {
BlockEditorProvider,
BlockList,
WritingFlow,
ObserveTyping
} from "#wordpress/block-editor";
import { SlotFillProvider, Popover } from "#wordpress/components";
import { useState } from "#wordpress/element";
import "#wordpress/components/build-style/style.css";
import "#wordpress/block-editor/build-style/style.css";
export default function MyEditorComponent() {
const [blocks, updateBlocks] = useState([]);
return (
<BlockEditorProvider
value={blocks}
onInput={(blocks) => updateBlocks(blocks)}
onChange={(blocks) => updateBlocks(blocks)}
>
<SlotFillProvider>
<Popover.Slot name="block-toolbar" />
<WritingFlow>
<ObserveTyping>
<BlockList />
</ObserveTyping>
</WritingFlow>
<Popover.Slot />
</SlotFillProvider>
</BlockEditorProvider>
);
}
And the typical hook error:
Error
Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See [link] for tips about how to debug and fix this problem.
I have setup a codepen to tyr it here: https://codesandbox.io/s/sleepy-proskuriakova-op59q
I looked up wordpress version of react and it seems to be 16.6.3 so set that in sandbox and used an older version of react scripts (2.1.8) that at the time was using 16.6.2 but no change in error. I tried several combinations of versions with no change.
What is actually causing this error? How can I get this component to load?
Here is a working codesandbox.
Things I've changed:
react and react-dom to 16.13.1 which is the version used in #wordpress/element
Had to add DropZoneProvider
Install #wordpress/block-library and call registerCoreBlocks
For more code examples you can check the official storybook docs, the source code is in the bottom panel, under the Story tab.

How to resolve react-video-js-player failing to load media

Hello I am trying to use the react video js player but I am getting the error below:
The media could not be loaded, either because the server or network failed or because the format is not supported.
At first, I thought maybe it was the video type because Initially it was a .mkvi video I then changed to mp4 and still nothing I get the same error can I please get help
Code Below: VideoList.js
import React from 'react';
import VideoPlayer from 'react-video-js-player';
const VideoList = (props) =>{
let videos = props.listVideos
return(
<div>
{videos.map(video =>{
return(
<div key={video.id}>
<h3>{video.lecturer}</h3>
<VideoPlayer src={video.video} width="720" height="420" playbackRates={[0.5, 1, 3.85, 16]}/>
</div>
)
})}
</div>
)
}
export default VideoList
Like I said on my comments, typically this error will occur if the video is not existing, has issues with the encoding, file extension, etc. See this example I've written.
In the end, I was correct and the video.video object was returning a relative path instead of an absolute path which resulted in an incorrect link.
Regarding the OP's current solution for this issue, this is not an ideal architecture because it will probably fail when you deploy to production, switch domains, or even just switch ports. Concantenating your base url is fine (e.g., http://127.0.0.1:8000/) but I would have this variable as a single source of truth probably residing at a state at the topmost component or as an environment variable so that anytime you change domains, ports, or IP you can simply change this variable and you won't have to go through all of your components 1 by 1.
Example implementation on Class based components:
Parent component:
state = {
base_url: `http://127.0.0.1:8000/api/`, // local dev api
// base_url: `https://production-server:80/api/` // live site api
// or an environment variable as described on my answer
}
Child component:
<VideoPlayer src={`${this.props.base_url}${content.video}`}
So I managed to find the problem behind this, so I was getting data from the API but when I tried to access the video the API was not giving the full URL that is:
http://127.0.0.1:8000/media/lectures/<here_the_name_of_the_lecture_video>
But the API was giving me a relative path media/lectures/<here_the_name_of_the_lecture_video>
So I had to give the remaining the URL that which the API does not give when I render in the video i.e I had to write the following
<VideoPlayer src={`http://127.0.0.1:8000/api${content.video}`}
So I am wondering
Currently, this solution works but is this solution technically good? Because I am to believe that the API should be giving everything that I need I just have to make requests.
Can you please assist me to come up with a more technically viable solution for this problem

React / Reactstrap Warning: Legacy context API has been detected within a strict-mode tree

This is brand new install - I have not put any transitions on the Alert component
To replicate the code it is simple
import React from "react";
import { Alert } from "reactstrap";
export const Index = () => {
return (
<div>
<Alert color='primary'>This is a primary alert — check it out!</Alert>
</div>
);
};
Error Msg: Please update the following components: Transition
How does one go about updating Transition or eliminating it all together?
In the event that someone comes here on after searching the question and is looking for insight this is it.
React strap (at the time of this post) uses the react-transition-group things fade in and out and menus slide up and down. After amalgamating the info on this subject here and on Github they are currently updating the library. I have finished the coding of that component by ignoring the warning.
It did not impede this iteration of that component. Happy Coding.
I have this same warning, and I fixed it changing in the index.js file, the value of <React.StrictMode> to <React.Fragment>.
Since this removes the warning, is not guaranteed that your can be bulletproof.
This issue was reported, and apparently fixed but I received the same error even with the updated source code. It's more than just the error as well - it can cause components to re-render
Here is one github thread from the reactstrap repo about this (but there are a number of them): https://github.com/reactstrap/reactstrap/issues/1340
There are a number of issues related to this warning though.
As best I can tell it has something to do with an item in Transition.js, and I think it may have to do with a this.context call when a component is 'entering'
But, the project I encountered this issue is the first React App I'm building, and I'm not quite ready to learn the Legacy Context API, so that's just my best guess and in the end I just opted for an alternative package.
I don't have the rep to put this in a comment, so the only answers I have are:
Report the issue to the reactstrap team and wait/assist with a fix
Use an alternative package

Add `console.log` to all `useEffect`

For development purposes I’d like to have the option to log all uses of useEffect inside my React app. Is there an easy way to extend the behaviour of this function? I’m using Webpack, in case this would provide us with an extra way of doing so.
Also, because this will lead to many console.logs, is there a way to tell them apart by providing information identifying the component that’s calling useEffect?
I would like to have this behaviour to “visually” check (in the console) if the application redundantly rerenders.
I would like to have this behaviour to “visually” check (in the console) if the application redundantly rerenders.
There is a library that does this for you: https://github.com/welldone-software/why-did-you-render#readme
The repo has a simple example to set it up:
import React from 'react';
if (process.env.NODE_ENV === 'development') {
const whyDidYouRender = require('#welldone-software/why-did-you-render');
whyDidYouRender(React);
}

How do I use/include third party libraries in react?

I would like to use jQuery and some other third party libraries not native to React. How can I use them in my React projects? I read componentDidMount is a good place to invoke third party libraries.
Unfortunately, I am unable to use the libraries as I keep getting " is not defined" errors even though I have properly linked script tags to those libraries in my index.html file.
You have two options, both demonstrated by a contrived example where I fade out a unordered list using jQuery. There are pros and cons to both approaches, I highlight both, and then provide my choice.
Option 1: Include the third party library in your index.html file
index.html
<head>
...
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
...
</head>
App.jsx
import React, { Component } from "react";
class App extends Component {
componentDidMount() {
// ** following two lines of code do the same thing
// using the first version, however, could potentially cause errors
// see "Referencing unimported libraries when using create-react-app"
$(this.refs.list).fadeOut(); // version 1
window.$(this.refs.list).fadeOut(); // version 2
}
render() {
return (
<ul ref="list">
<li>Item 1</li>
<li>Item 2</li>
</ul>
);
}
}
ReactDOM.render(<App />, document.getElementById("root"));
Referencing unimported libraries when using create-react-app
** If you are using create-react-app to scaffold your project, using the first version of code will throw errors. This is because create-react-app's default syntax linter (eslint) will throw errors during project compilation if you try to reference non-imported code (i.e. you never import $ from "jquery" since we reference the library in index.html). So when we referencing jQuery's global $ reference (which is very normal when using jQuery in the browser), we violate the basic principles of building modular JavaScript applications on Node.js. In Node, modules are the way of life and in those modules, we can only reference objects that we explicitly import. Without that explicit mention we technically break convention, hence the complaint from the linter.
Now both you and I know that the $ reference will become available once the application actually runs in the browser. When componentDidMount() is invoked, view has already mounted to the DOM and your third party library (in our example jQuery) is available to reference. Unfortunately the linter will block your react app from rendering because it thinks you are trying to reference undefined variables. Furthermore, the linter is platform agnostic and has no knowledge that your app is running in the browser (since JavaScript is no longer a browser-only language). This may be annoying but the linter is just doing its job, and, to some degree, it's absolutely right.
To avoid this error there are a few options:
Have eslint (the provided linter) ignore the lines where you make
reference the third party libraries using // eslint-disable-next-line (not preferred)
, or
Make use of window (preferred), or
Turn off the linter (not preferred), or
Don't use create-react-app (your preference, not recommend for beginners or even experts for that matter).
The first option can easily become a hassle if you make a lot of calls to the third party library. If you read up on componentDidMount, you know that at this point of invocation, you now have access to the window variable. You can access your library through window if the library attaches itself to the DOM's global window object. In our example, jQuery does just that and we can access jQuery's functionality via window.$
Option 2: Install the library using npm install <package-name> -S and import the library into relevant project files.
Terminal
npm i jquery -S
App.jsx
import React, { Component } from "react";
import $ from "jquery";
class App extends Component {
componentDidMount() {
$(this.refs.list).fadeOut();
}
render() {
return (
<ul ref="list">
<li>Item 1</li>
<li>Item 2</li>
</ul>
);
}
}
ReactDOM.render(<App />, document.getElementById("root"));
What is the right approach?
There are pros and cons of each approach: with first one you have the possibility of using a library that is hosted on a CDN and bank on the network effects and don't need to import third party code into your codebase. With the latter, you can make your code more readable and avoid the linter from blowing up.
For cons, the first approach may require you to add window to your third party library calls if you're using a linter (and you probably should); in the latter's case, sometimes third party libraries don't have their project code available to install through npm and you must download them manually and manually add them to your project source folder. In that case, using the first approach might make sense so that you don't have to manually import new versions of the library when they're released.
If at the end of all of this, you have failing code:
Ensure you installed the correct package,
Ensure you have included it directly in your index file or
imported it into your project and files where you are making library
specific calls.
If you know of other ways of accomplishing third party library integrations into react or find an error in this post, please feel free to edit this answer or add another answer.
The examples in this answer assume the execution environment is a browser, hence the use of window. If you are building a shell script or using react-native, it would be global, etc.
I needed to use the third party libraries as well as custom written javascript files inside of a React Component without loading them across other routes.
Kindly note am use a React Hook i.e. useEffect() thus you need a version of react which supports them.
Below is what worked for me.
import React, { useEffect } from "react";
const Airstrip = props => {
useEffect(() => {
// Now Attach All Third Party Scripts.
let threeJsScript = document.createElement("script");
let orbitJsScript = document.createElement("script");
let guiJsScript = document.createElement("script");
let mainJsScript = document.createElement("script");
// Hook Sources.
threeJsScript.src = `${process.env.PUBLIC_URL}/js/three.js`;
orbitJsScript.src = `${process.env.PUBLIC_URL}/js/orbit.js`;
guiJsScript.src = `${process.env.PUBLIC_URL}/js/gui.js`;
mainJsScript.src = `${process.env.PUBLIC_URL}/js/main.js`;
// Persist order of Loading.
threeJsScript.async = false;
orbitJsScript.async = false;
guiJsScript.async = false;
mainJsScript.async = false;
// Append to index.html
document.body.appendChild(threeJsScript);
document.body.appendChild(orbitJsScript);
document.body.appendChild(guiJsScript);
document.body.appendChild(mainJsScript);
// Do Clean ups
return () => {
document.body.removeChild(threeJsScript);
document.body.removeChild(orbitJsScript);
document.body.removeChild(guiJsScript);
document.body.removeChild(mainJsScript);
};
}, []);
return (
<div id="airstrip">
<canvas
id="canvas"
onClick={() => {
alert("Yeah");
}}
></canvas>
</div>
);
};
export default Airstrip;

Resources