I wan to refresh parent component from child class,
I read some articles but still confusing because parent is function and child is class
I appreciate your any help thank you very much.
Parent function component
export default function HeaderLinks(props) {
const classes = useStyles();
return (
<ChildWidget myHeaderLink={this}></ChildWidget>
Child Class
class AuthWidget extends React.Component {
constructor(props) {
super(props);
}
refreshParent(){
this.props.myHeaderLink.setState() ..??? maybe I need something equivalent to setState()?
I create a very small sample to display this useCase. You can check it here.
Just pass prop and onClick I handle it on the parent which update the state of parent and eventually that state change leads to the Re-renders of the component.
https://codesandbox.io/s/intelligent-dubinsky-w32dz?file=/src/App.js
Click on Button "Change parent Property" changes the parent state from "Hello World" to "Bye World"
Related
I have two components, a parent and a child.
Parent Component
const Parent = () => {
return (
<>
<div className="container"></div>
<div>more content</div>
<Child/>
</>
)
}
Child Component
const Child = () => {
const importantFunctionMustBeInChild = () => {
//Does a bunch of stuff that can't be done in the parent due to a lot of state that doesn't make sense to have in the parent
}
return (
<>
<button onClick={importantFunctionMustBeInChild}>Important Button</button>
</>
)
}
The problem is that I have a button in the child component. This button renders conditionally based off many different state toggles and has functions that can't be in the parent component because it wouldn't make sense to put it there and would take a long time to move all the state and functions up.
The issue is I now need to have the button to where the container div is in the parent component. Is there any way this can be done?
Going by the logic, you can assign a value(string, object, array) to parent component's state in the child component, right? So why can you not assign a function to the state and run it on click in the parent?
Definetely you can! In your child, assign function as a reference to the parent's state and thats it!
useEffect(() => {
// assign, don't invoke the function yet!
setFunctionToExecute(() => importantFunctionMustBeInChild);
}, []);
Here's a complete working demo
I have read a few questions, and I thought that just setting the id like the following should work:
<MyComponent id="myId"/>
But when I call document.getElementById() on the id, I get null and when I inspect the page, the component has an empty id.
What am I missing?
As #Lekhnath mentioned your MyComponent root elements id can be used to access the component. Something like below where you can access element with "componentId":
class MyComponent extends Component{
render(){
return <div id="componentId">
...your child component details here
</div>
}
}
I have a React component I built for a popup. PopupContent will receive a DOM element or another React component as a child.
class PopupContent extends React.Component {
render() {
return(
<div>
{React.cloneElement(this.props.children, {closePopup:this.props.closePopup})}
</div>
);
}
}
The closePopup prop sets a flag to show/hide the popup
closePopup(event){
event.preventDefault();
this.setState({
popupInView: false
})
}
The reason to pass closePopup to child is to close the popup from the child component.
This setup works well if the child is a custom React component:
<PopupContent>
<ContentOfThePopup />
</PopupContent>
But I get the Unknown Prop Warning if the child is a DOM element.
Warning: React does not recognize the closePopup prop on a DOM
element.
<PopupContent>
<div>Content Of The Popup </div>
</PopupContent>
I could use techniques explained here to distinguish between a DOM element and a React component. But I wanted to check with the community if there is a better way
what does this.props.children contain?
Shouldn't you be iterating over it?
render() {
return React
.Children
// this is the jsx version of cloneElenemnt,
// better to use in a render function
.map(Child => <Child.type ...Child.props ...this.props>)
}
Clone Element
React.Children.map
The unknown-prop warning will fire if you attempt to render a DOM element with a prop that is not recognized by React as a legal DOM attribute/property. You should ensure that your DOM elements do not have spurious props floating around.
You should ensure that you are not accidentally forwarding props that were intended to be interpreted by the parent component.
Also you can try {...this.props} format to pass your data instead of using cloneElement(element, this.props)
I've ended up checking the type of the child and conditionally removing the prop closePopup
Following condition will be true if the child is a HTML DOM element.
typeof this.props.children.type === 'string
I would like to know if there is a way to only render a parent component when its child is rendered and vis versa. If you google the title you find quite a few entries but nothing the would work for my case because my elements aren't undefined or null, for example. Imagine a Parent:
class Parent extends React.Component {
constructor(props){
super(props);
}
render() {
return (
<div>
<div className="container">
{this.props.children}
</div>
</div>
);
}
}
The following child might be depended on some settings. For instance, only show if a boolean is true.
class Child extends React.Component {
constructor(props){
super(props);
const showChild = Settings.get(...);
this.state = {
visible:showChild
}
}
render() {
const showHello = this.state.visible ? <div>Hello</div> : "";
return (
<div>{showHello}</div>
);
}
}
In my layout I scaffold it like this:
class Layout extends React.Component {
constructor(props){
super(props);
}
render() {
return (
<Parent>
<Child />
</Parent>
);
}
}
Is it possible to unmount Parent if that Child element is not rendered? Thank you.
Update: A use case is if I want this Parent and Child to be in a Layout and Parent has a container class with a larger padding or margin because it is still in the component tree. If Child isn't rendered a large gap remains within the Layout and it just looks odd.
React was not designed with this workflow in mind, in fact the opposite: data is explicitly passed down the DOM tree, while actions are passed upward. By extension, React must render your Parent before your Child.
I'd suggest refactoring your Parent and Child to the point where Parent is aware of which settings its Child needs; insofar as your Child component is engaged with:
<Child settings={settings} />
To reiterate, this is also a more natural approach to React, whereby data is explicitly passed downward, and not implicitly loaded in the Child (although there's always exceptions, like the ability of connect() components with react-redux). But a benefit to this approach is that now Parent is able to determine whether or not to render its Child.
But what about the rendering of Parent? Don't we want to inhibit that too? If you do, then you'll need your Layout component to be aware of what it's Parent component needs, therefore:
<Parent settings={settings} />
This is a common approach to React since rendering down the DOM hierarchy is a must.
You could conditionally render in your Parent component by checking to see if it has any children.
Use this.props.children.length to see if there are any, if yes, render normally, if not return an empty element.
I have the following Vue.js components, which basically are supposed to have a radiobutton-like behaviour:
// Parent Component
<template>
<child-component
v-for="element in elements"
</child-component>
</template>
<script>
import ChildComponent from './Child.vue'
export default {
components: {
ChildComponent
},
props: {
elements: Array
},
methods: {
activate(e) {
for (let i of this.$children) {
i.active = false;
}
if (e < this.$children.length) {
this.$children[e].active = true;
}
}
}
}
</script>
and
// Child Component
<template>
{{active}}
</template>
<script>
export default {
props: {
active: Boolean
}
}
</script>
This works fine but only the parent can decide to activate one of the children (and thus deactivate all others).
I want however also be able to allow each child to activate itself (and by a magic property of its parent, deactivate all other siblings).
Obviously I do not want each child to know about its siblings and mess with their .active prop (super bad design).
I would rather not have a children communicate back up to the parent and call some method (still bad design as I could only reuse the child components in parents that have activate() method).
Instead I would like the parent to listen to changes to all children active props and take action when one of them changes. That way the parent entirely encapsulates the radio button behavior.
How can this interaction be implemented in Vue.js?
Take a look at two-way binding: http://vuejs.org/guide/components.html#Prop_Binding_Types
This allows you to sync a property's value in both directions, meaning the parent or the child has access to change the variable. Then you can watch for changes on the parent and update accordingly.
I think a better option would be to create a RadioSet component, which then would house a number of radio buttons. This would eliminate your concern about a parent having to have the activate() method. You could simply pass in an object with a series of id and values that could be used to generate the buttons.