React.js - call child function from parent - reactjs

Is it possible to call a function of a child component on a direct way without creating a 'helper'-function on the top-level?
Can you explain me the right way to pass this problem?
export const AppComponent = () => {
return (
<ParentDiv>
<ChildDiv />
<ParentDiv />
);
}
const ParentDiv = (props) => {
return (<div>Parent{props.children}<button>do something...</button></div>);
}
const ChildDiv = (props) => {
const submitButton = () => {
console.log('do something...');
}
return (<div>Child</div>);
}

Related

React: Is there a way to access component state from function in another file?

I've a react component which includes a large function that updates the component state, the function is large so I want to move it to a separate file and export it in the react component. But I don't find anyway to access the component state if I move the function to its own file.
Is there anyway to do this ?
example:
component.tsx
import { myFunction } from './function.ts'
const [toggle, setToggle] = useState(false)
const my_component = () => {
return (
<div>
<button onClick={myFunction}>Run function</button>
</div>
)
}
export default my_component
function.ts
export const myFunction = () => {
// do something that updates `toggle`
}
you can do the logic apart from the component and return the result to the component. have a look at the code below.
https://codesandbox.io/s/hopeful-dubinsky-930p7?file=/src/App.js
This is just a raw example of what you can do with custom state hooks (reference: https://dev.to/spukas/react-hooks-creating-custom-state-hook-300c)
import React from 'react';
export function useMyFunction(value) {
const [toggle, setToggle] = React.useState(value || false);
const myFunction = () => {
// do something that updates `toggle` with setToggle(...)
}
return { toggle, myFunction };
}
import { useMyFunction } from './function.ts'
const my_component = () => {
const [toggle, myFunction] = useMyFunction(false)
return (
<div>
<button onClick={myFunction}>Run function</button>
</div>
)
}
export default my_component
This can be achieved by 2 different ways one using HOC components and another just by using functions.
Approach 1: Using HOC
handler.js
const withHandlers = (WrappedComponent) => {
class HandlerComponent extends Component {
state = {toggle:false};
myFunction = () => {
//Do your update here
}
render() {
return <WrappedComponent
toggle={this.state.toggle
myFunction={this.myFunction}
/>
}
};
my_component.js
const my_component = (props) => {
return (
<div>
<button onClick={props.myFunction}>Run function</button>
</div>
}
export default withHandlers(my_component);
Approach 2: Using Functions
handler.js
export const myFunction(toggle) => {
return !toggle; //return the changed value
}
my_component.js
const my_component = () => {
const [toggle, setToggle] = useState(false);
const myFunction = () => {
setToggle(handler.myFunction); //the state will be passed as a parameter by default
};
return(
<div>
<button onClick={myFunction}>Run function</button>
</div>
);
};
For the toggle to work, it must be passed to the function as a props then for update it used state management (redux or react context).
The best solution is to define the toggle in the function itself and pass it a Boolean props to control it.
import { myFunction } from './function.ts'
const my_component = () => {
return (
<div>
<button onClick={myFunction(false)}>Run function</button>
</div>
)
}
export default my_component
function.ts
export const myFunction = (props) => {
const [toggle, setToggle] = useState(props || false);
// your codes
};

ReactJs Functional Component - How to call function from outside?

How to call a function from outside of the functional component.
I have a functional component like this
import React, { useState } from 'react';
const Hello = () => {
// call updateField() here
};
const Headline = () => {
const [greeting, setGreeting] = useState(
'Hello Function Component!'
);
// Function inside Headline, I want to call this function in Hello()
const updateField = () => {
}
return <h1>{greeting}</h1>;
};
export default Headline;
I want to call updateField() in Hello() outside of Headline(). Please suggest.
Here are two ways to do this,
Method 1: Move the common state to a parent component
const ParentComponentWithHelloAndHeadline = () => {
const [field, setField] = useState()
const updateField = () => { ... }
return (
<>
<Headline field={field} updateField={updateField} />
<Hello updateField={updateField} />
</>
)
}
Method 2: Use React.Context (avoids prop-drilling, incase that is a concern using method 1)
const CommonContext = React.createContext({
field: 'commonField',
updateField: () => { ... }
})
const Hello = () => {
const { field, updateField } = useContext(CommonContext)
// call updateField() here
};
const Headline = () => {
const { field, updateField } = useContext(CommonContext)
const [greeting, setGreeting] = useState(
'Hello Function Component!'
);
return <h1>{greeting}</h1>;
};
export default Headline;
function RootApp() {
return (
<CommonContext.Provider>
<Headline />
...
...
<Hello />
</CommonContext.Provider>
);
}

Why using render-props instead of just passing the component as a prop?

Just out of curiosity, what is the difference between this:
const Parent = ({Child}) => {
return <div><Child name="pedro"></Child></div>
}
const Child = ({name}) => {
return <div>{name}</div>
}
export default function App() {
return (
<Parent Child={Child}></Parent>
);
}
And this:
const Parent = ({render}) => {
return <div>{render("pedro")}</div>
}
const Child = ({name}) => {
return <div>{name}</div>
}
export default function App() {
return (
<Parent render={name=><Child name={name}></Child>}></Parent>
);
}
Both achieve the same result but for some reason the second way (render props) is waaaay more popular than the fist one and I just can't find any differences or articles talking about it.

Will React memoize component created during children.map?

If I have a setup like the following:
const ChildComponent = React.memo((props) => {
return (<>...</>);
});
const ParentComponent = (props) => {
return (
{React.Children.map(props.children, child => {
return <div>{child}</div>;
)}
);
}
Assuming child.props are identical, will React know to memoize child or will it rerender each time?
Changed the setup to the following:
const ChildComponent = React.memo((props) => {
return (<p>{props.a}</p>);
}, (prev, next) => {
if (prev.a === next.a) { console.log('memo'); return true; }
console.log('no memo'); return false;
});
const ParentComponent = (props) => {
return (
{React.Children.map(props.children, child => {
return <div>{child}</div>;
)}
);
}
const App = () => {
return (
<ParentComponent>
<ChildComponent a='a'/>
<ChildComponent a='b'/>
<ChildComponent a='c'/>
</ParentComponent>
);
}
And I see memo in console. This doesn't seem to be like an exhaustive answer by any means, but I'd assume this means it works.

how can put ref to props.children

I want wrapping module for multi use.
so, I make an ItemComponent
export const DragItem = (props: DragProps) => {
const [{... }, fooRef] = useFoo({
})
return (
props.children // how can i send fooRef to here??
)
}
I should send ref to props.children
Is it possible?
check this : https://codesandbox.io/s/gracious-williams-ywv9m
You need to use React.cloneElement to attach/pass extra data to children
export const DragItem = (props: DragProps) => {
const [foo, fooRef] = React.useState({});
var childrenWithRef = React.Children.map(props.children, function(child) {
return React.cloneElement(child, { fooRef: fooRef });
});
return childrenWithRef;
};
I got it.
export const DragItem = (props: DragProps) => {
const [{... }, fooRef] = useFoo({
})
return (
React.cloneElement(props.children, { ref: fooRef })
)
}

Resources