Add `console.log` to all `useEffect` - reactjs

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

Related

How to prevent refresh of list over API after drag & drop with beautiful DND?

I simulated my Context + DND problem in https://codesandbox.io/s/adoring-booth-33vqo . I have other components which will be added to this example and I will use a Context hook to share values across the page.
After the initial render, everything looks fine. The idea of the list is to change the order within itself and when ones changes the order with drag-drop, it throws an "Invalid Hook" error.
So the (first) real question is, what is triggering this error which is linked to the line
const { lang1Library, updateLang1Library } = useContext(LangContext)
;
Thanks in advance for your help.
Geo
It's not a good approach to provide a link for the whole project even if it is small. But I had a quick look and there's at least one thing you're doing wrong:
// DragEndFct.js
export default function DragEndFct(result, libName) {
const { lang1Library, updateLang1Library } = useContext(LangContext);
This is not React component, but it uses a hook - and it is wrong. Hooks have a special meaning in React and should be used properly (Rules of Hooks).
You can't use hooks inside regular functions and expect them to work. That is why you are getting that error.
So, there are many ways you can try to fix this. For instance, DragEndFct is a regular function, you can declare more arguments and pass stuff you get from context:
// you are using it in components right ?
function DragEndFct(result, libName, param3, param4) {}
// so you probably have access to the context there
// and can pass data from the context when you call it.
// something like this
onDragEnd={function (result) {
console.log();
DragEndFct(result, StaticVars.LANG1_LIBRARY_NAME, lang1Library, updateLang1Library);
}}
You could even make DragEndFct to be a React component - it can just return null (which means no UI will be rendered) but in that case you will have hooks and all other stuff there. It really depends on what you need and how you will use it.

Must React Router be used if the goal is just to get one or two URL params?

If we use a React app and hope to compare two ways of doing things, by passing in v=1 or v=2
www.website.com/foo/?v=1
must React Router or some npm package be used to get the value? Does React itself has such a mechanism? Or else, we can just use document.location.search and parse it like in the old days?
React doesn't have a built-in mechanism for that, but - why not just parse document.location.search? If you're not looking for the extra functionality, go ahead and do that. There are easy ways built in to handle such things, for example URLSearchParams:
const search = '?my=foo&another=bar' // or document.location.search
const params = new URLSearchParams(search)
console.log(params.get('my'))
console.log(params.get('another'))
Stick this into a component directly or into a util function and import it to use in a component.

Mocking React-Redux Store With Jest

Our React-Redux App uses create-react-app. We’re trying to back-apply Jest/Enzyme/redux-mock-store to a large code base. Our src/store.js file is the standard react-redux script that runs the reducers and constructs an initial state. This src/store.js is central to the problem.
Problem is that when we start the jest test-run, jest loads src/store.js 7 times, and then (roughly) once for every test. I must suppress this and can’t figure out how. The reason I must suppress it is that it always leaves the store in its initial state and there is one crucial AppConfig property in that store which must be populated to prevent javascript errors that stop jest. I already have a function which returns a mock store for use with the Provider. That works well. But our components call out from constructor(), componentDidMount(), etc to api functions. Those api functions don’t see the state dropped from Provider. Instead, the api functions do stuff like this:
// AppConfig is an immutable Map
const { AppConfig } = store.getState();
const stuff = AppConfig.get(‘stuff’).toJS();
That’s a JS error because AppConfig is empty and toJS() is called on undefined. (That can never be a problem in run-time because we construct no component without AppConfg being ready.) There are 2 solutions involving refactoring the App that I can do. But I’d rather figure out how to properly use jest. How can I supply the mock redux state without it getting clobbered by jest's repeated loads of src/store.js???
This is killing me. What in Jest, create-react-app, or ??? initiates these unwanted loads of src/store.js? How to override? Is there a config that causes jest to call my function instead of src/store.js?
I figured out my own problem. Will post here in case someone else that is new with jest may benefit from my folly.
Jest does not load src/store.js. The culprit is my shallow component tests because the components have statements like this:
import StuffService from '../../api/stuff';
The calls to the api from the component look like this:
// e.g. from componentDidMount
StuffService.get.myRequest();
But in the es6 module that defines StuffService, at the top we have something like:
import store from '../../store';
// lower in the js file, we have code as shown in my previous post:
const { AppConfig } = store.getState();
That's what is causing src/store to keep running. Will study Jest's Manual Mocks for a solution.

The role of storybook when testing of React application is conducted

I am new to React and recently I found out there is the tool called storybook which basically helps to test our React components in isolated manner. However, I also found out that storybook is used when we test our React application, that is, there happens the comparison of snapshots. The question is what is the reason for testing the difference of snapshots? I mean, is it like we create a certain component and create a snapshot for it to ensure that other developers do not change that component accidentally, that is, snapshot in storybook helps us ensure there is no accidental change of components that we created. Is it true?
You create snapshot tests to ensure that your Components renders correctly given a certain input.
This is a way to make sure your code still behaves the way it was intended to. It's to ensure you don't accidentally break something in your code base, but also to alert you when anything changes.
An example:
Say I have a component called ProfileLink that generates a link to a user account:
function ProfileLink(props) {
return <a href ={get_url(user.id)}>{props.user.profileName}</a>;
}
and somewhere else I have a function called get_url:
function get_url(id) {
return "www.example.com/user/" + id;
}
Now, to ensure that my ProfileLink is always working, I can create snapshot, and everytime my tests run, the snapshot will be compared to the current rendered component.
Say someone were to change the get_url function, they might not be aware that it's used in ProfileLink, but as soon as the tests are run, you'll know that something has changed in the ProfileLink component as well.

How React Component expose data to external app?

Let's say i have a React Component <forecast id="test"/>. And i want import this component into a legacy project which only have jquery involved.
Is it possible to get the value of this component like document.querySelector('#test').value?
I got some information from React website, that we cannot access data from outside the component. The recommended way is dispatching data from inside of the component.
My question is, the way to dispatching data is behind of the component implementation. Is it means that i have to read the source code of component in case i don't know how it works?
If this is true, i won't think React is free to inject to any product, it cost too much.
If you want to inject some React to your project you should do it with some independent part of your system.
If you have tightly coupled code base its always high cost to add any new technology to it. So its not a React problem. Try to find some independent module or subapplication in your system and move it to React. If you cannot find one, try to refactor existing code first.
You need to write a plain JS wrapper to do it. Something like this might work
function Forecast(element) {
this.value = initialValue;
React.render(<forecast onChange={onChange.bind(this)}/>, element);
function onChange(newValue) {
this.value = newValue;
}
}

Resources