Is there a didmount method for function? - reactjs

I've looked a lot for that, but never actually found answer for it.
I have a function (not a class) that returns some React.Component and I like using it due to how easy it is to use states. Normally I use classes, but there are some places it just feels better to use a function.
Is there any way to check if the function gets didmounted?
I don't want to create any memory leaks.
Example function:
export default function foo() {
const [bar, setBar] = React.useState(false)
function looping() {
<some code with useState>
}
return (
<div>Something</div>
)
}

You can use useEffect hook:
export default function foo() {
const [bar, setBar] = React.useState(false)
useEffect(() => {
console.log('mounted')
return () => {
console.log('unmounted')
}
}, [])
function looping() {
<some code with useState >
}
return (
<div>Something </div>
)
}
There's also useLayoutEffect, which works synchronously.

Related

Returning a function vs setting a const equal to a function in React

I'm relatively new to React and was wondering why I'm getting a Functions are not valid as a React child. This may happen if you return a Component instead of from render error.
In my code there is an existing:
const SomeConst = SomeFunctionThatReturnsAComponent();
Now I am trying to update that const to have some logic before calling the function like so:
const SomeConst = (props) => {
//Some logic
return (SomeFunctionThatReturnsAComponent()());
}
Here is SomeFunctionThatReturnsAComponent():
const Template = component => (props) => {
const ReturnThisComponent = props => <Component component={component}, {props} />
return ReturnThisComponent;
}
The usage of SomeConst remains the same as the original implementation:
const SomeComponent = (props) => {
return (<SomeConst prop1="foo"/>)
}
I am wondering why this is not functionally the same thing and why I am getting this error. I have not been able to find a post that gets this error with the way I have it implemented. They are different implementations that arrive at this same error so they were not that much of a help to me.
If there is another post, I would kindly ask to link me to it and I will quickly remove this post and link it to the other post for future people.
Please let me know if I can clarify anything, I have tried to create this post as a repex.
tl;dr - you are missing one function call.
SomeFunctionThatReturnsAComponent()();
what does each parentheses do?
The first parens are calling the first function, that returns a function that returns ReturnThisComponent. If you call this function (Template) only once, you will still return a function (props) => { ... };
const Template = component => (props) => {
const ReturnThisComponent = props => <Component component={component}, {props} />
return ReturnThisComponent;
}
So either - call the function twice, or - remove the second curried function (props) => (and I think this is what you wanted to achieve). So it will look like:
const Template = (component) => {
const Component = component;
const ReturnThisComponent = (props) => <Component {...props} />;
return ReturnThisComponent;
}

alternative to call dispatch from a exported function

I am getting the error
React Hook "useDispatch" is called in function "move" which is neither a React function component or a custom React Hook function
I have a component boardSquare which imports and calls handleMove
import { handleMove } from './Game'
export default function BoardSquare({ piece, black, position,isFromSquare,isToSquare}) {
handleMove(value)
}
and inside inside game.js which holds handleMove
there is also imports chess.js which provides a string value
//game.js
import * as Chess from 'chess.js'
const chess = new Chess()
export function handleMove() {
const chessFen = chess.fen()
const dispatch = useDispatch();
dispatch(setFen(chess.fen()))
}
obviously i can't call dispatch there though i need an alternative as eventually i want to do the following
which is
inside Gameapp.js
have
function GameApp() {
const fen = useSelector(state => state.fen)
const [board, setBoard] = useState([])
useEffect(() => {
setBoard(fen
}, [fen])
}
return (
<Board board={board}
/>
)
because i want to update Board with the fen value when it is called in game.js
You can get the function dispatch in your component BoardSquare and use it as a callback to handleMove :
export default function BoardSquare({ piece, black, position,isFromSquare,isToSquare}) {
const dispatch = useDispatch();
return <div onClick={(value) => handleMove(value, dispatch)}/>
}
function handleMove(dispatchFunction) {
const chessFen = chess.fen()
const dispatch = useDispatch();
dispatchFunction(setFen(chess.fen()))
}
You could also return the value to dispatch from handlemove and dispatch it in your component, which might look cleaner and be easier to test
export default function BoardSquare({ piece, black, position,isFromSquare,isToSquare}) {
const dispatch = useDispatch();
return <div onClick={(value) => dispatch(handleMove(value))}/>
}
function handleMove(value) {
const chessFen = chess.fen()
return setFen(chess.fen())
}
As an aside, please try to make your code more coherent/readable when looking for help, you probably tried to be succint, but your component BoardSquare doesn't make sense as you wrote it in your question, handlemove is given a value not present in its signature, and the indentation is off
I just made another function called getFen() and did it like so
export function getFen(){
return chess.fen()
}
import getFen()
handlemove(){
fen = getFen()
dispatch(setFen(fen)
}

How to call react function from external JavaScript file

I have read this post [ https://brettdewoody.com/accessing-component-methods-and-state-from-outside-react/ ]
But I don't understand.
that is not working on my source code.
it's my tsx file
declare global {
interface Window {
fn_test(): void;
childComponent: HTMLDivElement; <-- what the... ref type????
}
}
export default function Contact(): React.ReactElement {
....
function file_input_html( i:number ): React.ReactElement {
return (
<form id={`frm_write_file_${i}`} .... </form>
)
}
....
return (
<div ref={(childComponent) => {window.childComponent = childComponent}}>
....
)
it's my external javascript file
function fn_test(){
window.childComponent.file_input_html(3)
var element = document.getElementById("ifrm_write_file");
// element.value = "mystyle";
}
How can i call file_input_html function?
plase help me ...
You have some logic here that doesn't completely make sense.
In your class, you define file_input_html, which returns a component.
Then, in fn_test, you call attempt to call that function (which doesn't work -- I'll address that in a minute), but you don't do anything with the output.
The article that you linked to tells you how to get a ref to a component (eg the div in this case) -- not the actual Contact, which doesn't have a property named file_input_html anyway -- that's just a function you declared inside its scope.
What I'm assuming you want to happen (based on the code you shared) is for your external javascript file to be able to tell your component to render a form with a certain ID and then be able to get a reference to it. Here's an example of how to do this (it's a little convoluted, but it's a funny situation):
const { useState } = React
const App = (props) => {
const [formId, setFormId] = useState(2)
useEffect(() => {
window.alterFormId = setFormId
},[])
return (<div id={"form" + formId} ref={(ourComponent) => {window.ourComponent = ourComponent}}>
Text {formId}
</div>);
}
setTimeout(() => {
window.alterFormId(8);
setTimeout(() => {
console.log(window.ourComponent)
window.ourComponent.innerText = "Test"
}, 20)
}, 1000)
ReactDOM.render(<App />,
document.getElementById("root"))
What's happening here:
In useEffect, I set alterFormId on window so that it can be used outside of the React files
Using the technique you linked to, I get a ref to the div that's created. Note that I'm setting the ID here as well, based on the state of formId
The setTimeout function at the end tests all this:
a) It waits until the first render (the first setTimeout) and then calls alterFormId
b) Then, it waits again (just 20ms) so that the next run loop has happened and the React component has re-rendered, with the new formId and reference
c) From there, it calls a method on the div just to prove that the reference works.
I'm not exactly sure of your use case for all this and there are probably easier ways to architect things to avoid these issues, but this should get you started.
안녕하세요. 자바스크립트로 흐름만 알려드리겠습니다
아래 코드들을 참고해보세요.
iframe간 통신은
window.postMessage API와
window.addEventListener('message', handler) 메시지 수신 이벤트 리스너 로 구현할 수있습니다. 보안관련해서도 방어로직이 몇줄 필요합니다(origin 체크 등)
in parent
import React from 'react';
export function Parent () {
const childRef = React.useRef(null);
const handleMessage = (ev) => {
// 방어로직들
if (check ev.origin, check ev.source, ....) {
return false;
}
console.log('handleMessage(parent)', ev)
}
React.useEffect(() => {
window.addEventListener('message', handleMessage);
// clean memory
return () => {
window.removeEventListener('message', handleMessage);
}
})
return (
<div>
<iframe ref="childRef" src="child_src" id="iframe"></iframe>
</div>
)
}
in child
import React from 'react';
export function Iframe () {
const handleMessage = (ev) => {
console.log('handleMessage(child)', ev)
}
const messagePush = () => {
window.parent.postMessage({ foo: 'bar' }, 'host:port')
}
React.useEffect(() => {
window.addEventListener('message', handleMessage);
// clean memory
return () => {
window.removeEventListener('message', handleMessage);
}
})
return (
<div>
<button onClick={messagePush}>Push message</button>
</div>
)
}

Convert react class to react function

Hi so I have two files and i want to convert one of them into a react functional component. The first one is PuzzleGrid and it will call the function Grid.getMatrix()
export const PuzzleGrid = () => {
const newMatrix = GridLib.getMatrix();
}
and the next is Gridlib which is a react class :
export class GridLib {
static getMatrix() {
return Array(6).fill(Array(6).fill(0));
}
}
I want to be able to convert the class into a function, this is what i have, however i am getting an error. does anyone understand why?
export const GridLib = () => {
GridLib.getMatrix = {
Array(6).fill(Array(6).fill(0));
}
}
You can simply return the results of the getMatrix method:
export const GridLib = () => {
return Array(6).fill(Array(6).fill(0));
}
However, this will cause a problem for your PuzzleGrid component, as it depends on GridLib having a getMatrix method. You would have to simply have PuzzleGrid return a GridLib for it to work as such:
export const PuzzleGrid = () => {
return <GridLib />
}
However this pattern is a bit silly and repetetive. I feel like there must be more going on to your question, but you may have reduced it down too much and stripped away some important details. What is the larger context of this issue?
Just use a function properties to declare a "static method"
export const GridLib = () => {
return <View/> ;
}
GridLib.getMatrix = () => {
return Array(6).fill(Array(6).fill(0));
}

Reactjs hook that uses other hooks

I needed to create a custom hook which is supposed to contain all the handlers that will be used everywhere in my page. My requirements were;
Handlers are supposed to be accessible from all the components in the page
Handlers should be able to use other hooks, like useContext
So, created a useHandlers hook sandbox
However, couldn't make the LogHandler accessible from the page, receving LogHandler is not a function
Any idea?
The issue why you're getting LogHandler is not a function is because it's undefined and it doesn't get initialized until HandlerComp gets called:
export const userHandlers = (): IUseHandlers => {
// initialization skipped, so `LogHandler` is undefined
let LogHandler: () => void;
const HandlersComp: React.FunctionComponent<HandlersProps> = (
props: HandlersProps
) => {
// initialized here, but that's after `HandlersComp` gets caled
LogHandler = () => {
console.log("Hi from LogHandler");
};
return <></>;
};
return { HandlersComp, LogHandler };
}
I suggest you move the initialization step from HandlersComp like so:
export const useHandlers = (): IUseHandlers => {
const LogHandler: () => void = () => {
console.log("Hi from LogHandler");
};
const HandlersComp: React.FunctionComponent<HandlersProps> = (
props: HandlersProps
) => {
LogHandler()
return <></>;
};
return { HandlersComp, LogHandler };
};
Some notes:
HandlersComp looks like it should be a separate and reusable component, rather than a hook
LogHandler also looks more like a utility function, rather than a hook
LogHandler shouldn't be using PascalCase for naming as that should be "reserved" for React components; HandlersComp is fine, since it looks like it's a component

Resources