arrow function inside functional component is undefined react hooks - reactjs

I'm trying to make a like button counter with react hooks. I have defined the arrow function this way, but I'm getting IncreaseLikeHandler is undefined.
import {useState} from "react";
import './App.css';
function App() {
IncreaseLikeHandler = () =>{
setLikeCounter(likeCounter+1);
};
const [likeCounter, setLikeCounter] = useState(0);
const [dislikeCounter, setDislikeCounter] = useState(0);
return (
<div className="App">
<p>test</p>
<button onClick={IncreaseLikeHandler}>like</button>
<button>dislike</button>
<div>{likeCounter}</div>
</div>
);
}
export default App;

You first have to declare it then you can use it
without declaration eslint will complain
'IncreaseLikeHandler' is not defined. (no-undef)eslint
const IncreaseLikeHandler = () => {
setLikeCounter(likeCounter + 1);
};

Inside the fanction component you must use (const, let and var) to define the functions.

Related

When I declare function in useEffect, it is not declared in html

I am implementing to change the state depending on it is hovered or not. But if I make it like the first code below, Too many re-renders. error will occur. In order to solve this problem, I used the useEffect to render only when the state changes, but an error called onHover is not defined occurs that the function declared in the user effect was not declared.
not using useEffect
import "./styles.css";
import { useState } from "react";
export default function App() {
const [isHover, setIsHover] = useState(false);
return (
<button onMouseEnter={setIsHover(true)} onMouseLeave={setIsHover(false)}>
click
</button>
);
}
using useEffect
import "./styles.css";
import { useEffect, useState } from "react";
export default function App() {
const [isHover, setIsHover] = useState(false);
useEffect(()=>{
const onHover = () => {
setIsHover(true)
}
},[isHover])
return (
<button onMouseEnter={onHover()} onMouseLeave={setIsHover(false)}>
click
</button>
);
}
What should I do to use the function declared in useEffect?
As you just want to setState so no need to use useEffect.
You can use without using useEffect as below.
import "./styles.css";
import { useState } from "react";
export default function App() {
const [isHover, setIsHover] = useState(false);
return (
<button onMouseEnter={() => setIsHover(true)} onMouseLeave={() => setIsHover(false)}>
click
</button>
);
}
It has to do with scope. The onHover function is defined within the useEffect hook, so it goes out of scope once you're out of the hook's block. You'll have to define it directly inside the component, outside of any other block scope, and simply call it inside useEffect.
It will still result in onHover called so many times until the mouse leaves the element in question. To prevent it, you could add a condition like so:
const onHover = () => {
if (!isHover) {
setIsHover(true);
}
}

ref.current is always undefined?

I need to use functional component ,so I can't use useRef directly. here is my code:
import React,{forwardRef,useImperativeHandle,useRef,useEffect} from "react";
import "./style.css";
export default function App() {
const ref_ = useRef();
useEffect(()=>{
console.log(ref_)
})
console.log(ref_)
return (
<div>
<Demo/>
</div>
);
}
const Demo = forwardRef((props,ref)=>{
useImperativeHandle(ref,()=>({
toggle(){
console.log(123);
}
}))
return(
<div ref={ref}>1234</div>
)
})
online code :
https://stackblitz.com/edit/forwardref-z68drh?file=src/App.js
and I want to trigger child component's function on parent component... can anyone help me?
You need to pass the ref itself to Demo component:
function App() {
const ref = useRef();
return <Demo ref={ref}/>;
}
Then you can use ref.current.toggle() due to useImperativeHandle.
https://stackblitz.com/edit/forwardref-z68drh-epz2xf?file=src/App.js

React custom hooks not working as expected

I am trying to implement a very simple custom hook called useOpen that simply returns a boolean (isOpen). I want to show or hide some text in App.js based on isOpen state. Currently, nothing is being rendered and trying to console.log(isOpen) in App.js gives me undefined. Thanks in advance!
App.js
import React from 'react'
import useOpen from './CustomHooks/useOpen'
function App () {
const {isOpen} = useOpen;
return (
<div className='App'>
{isOpen && <p>isOpen</p>}
</div>
)
}
export default App
useOpen.js
import { useState } from 'react'
export default function useOpen() {
const [isOpen, setIsOpen] = useState(true)
return { isOpen }
}
You’re missing the parens on useOpen. Should be useOpen().
const {isOpen} = useOpen; // missing ()
const {isOpen} = useOpen();
Try to call function useOpen at the component.
you need to execute the hook to get its value
and you don't need to put it in a object to deconstruct it on the other side
App.js
import React from 'react'
import useOpen from './CustomHooks/useOpen'
function App () {
//const {isOpen} = useOpen;
const isOpen = useOpen();
return (
<div className='App'>
{isOpen && <p>isOpen</p>}
</div>
)
}
export default App
useOpen.js
import { useState } from 'react'
export default function useOpen() {
const [isOpen, setIsOpen] = useState(true)
//return { isOpen }
return isOpen
}

How to use import () to dynamically load components in React?

I tried to use import() instead of React.lazy to dynamically load components, but it didn't work.
App.js
import React, { useState } from 'react';
function App() {
const [Com, setCom] = useState(null);
const handleClick = () => {
import("./A.js").then(c => {
//console.log(c.default)
setCom(c.default)
})
}
return (
<div>
<button onClick={handleClick}>Load</button>
{ Com ? <Com /> : null }
</div>
);
}
export default App;
A.js
import React from "react";
export default function A () {
return (<div>A</div>)
}
Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.
In fact, I printed out c.default. It's really a function.
c.default
ƒ A() {
return react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", {
__source: {
fileName: _jsxFileName,
lineNumber: 4
},
__self: this
}, "A");
}
Actually, it's not related to the dynamic import but the useState implementation. For example:
import Comp from "./A";
function App() {
const [Com, setCom] = useState(Comp);
return (
<div>
<Com />
</div>
);
}
Will throw the same error. That's because when you call useState(Comp), Comp "function" (which is the Component) been execute (you can test it by removing any <Com /> from the code and adding console.log inside A. The console.log still appears).
As a result Com is no longer a Component but a JSX element. When you try to render JSX element in a function way (meaning wrapping it with < and />, this error thrown.
The solution is either to set Com as a component (() => Com) or to render it as a JSX child ({Com})
import React, { useState } from "react";
function App() {
const [Com, setCom] = useState(null);
const handleClick = () => {
import("./A.js").then(c => {
//console.log(c.default)
setCom(c.default);
});
};
return (
<div>
<button onClick={handleClick}>Load</button>
{/* <Comp /> */}
{Com}
</div>
);
}
export default App;
https://codesandbox.io/s/answer-for-httpsstackoverflowcomq62125854863110-jj2wu
BTW, you can see the difference by console.dir the original outcome of import Comp from "./A"; and the outcome of useState(Comp)
import Comp from "./A";
function App() {
const [Com, setCom] = useState(Comp);
// console.log(1, Com, 2, Comp);
console.dir(Com) // Object
console.dir(Comp) // ƒ A()
//...
}
If setState is called with a function, it will be executed with the previous value as the argument.
const [count,setCount] = useState(0)
setCount(prevCount => prevCount + 1)
In your case, rather than updating the state with the imported function, React will execute it and the result will be set as the state.
Solution:
setCom(() => c.default)

How to test a function passed to another component?

How do I write a unit test to cover the logic in fooFunction?
The logic could be moved out to another file in order to achieve test coverage, but what if I don't want to?
FooComponent.jsx:
import React, { useState } from 'react';
import FooContext from './FooContext';
import BarComponent from './BarComponent';
function FooComponent() {
const [value, setValue] = useState();
const fooFunction = inputValue => {
setValue(inputValue * 2);
};
return (
<div>
<span>Hello world!</span>
<BarComponent inputFunc={fooFunction} />
</div>
);
}
export default FooComponent;
How do I test it? Is the only option to not declare the function inside the FooComponent scope?

Resources