I have a little confused about children component. As I know children component is the component nested inside other component, for example
<Parent>
<Child />
</Parent>
But what is the component inside the render function of Parent component. What is it called? For example of Parent component
class Parent extends React.Component {
render() {
return (
<ComponentX>
{this.props.children}
</ComponentX>
)
}
}
Is ComponentX called a children of Parent Component?
I appreciate any explanation. Thanks in advance
Is ComponentX called a children of Parent Component?
NO.
ComponentX is called an Enclosing component of Parent's children.
Similar to how React.Fragments are used, without an enclosing element, there will be a warning:
Parse Error: Adjacent JSX elements must be wrapped in an enclosing tag
class Parent extends React.Component {
render() {
return (
<ComponentX>
{this.props.children}
</ComponentX>
)
}
}
this.props.children here is of Parent, and when you pass them into children of ComponentX. In ComponentX you will got this children.
Example:
class Parent extends React.Component {
render() {
return (
<ComponentX>
{this.props.children} // Here is children of Parent
</ComponentX>
)
}
}
In ComponentX:
class ComponentX extends React.Component {
render() {
return (
<div>
{this.props.children} // Here is children of ComponentX that you passed
// in above
</div>
)
}
}
In this case, you get children of Parent to use for childrent of
ComponentX
Related
I want to re-render my child component without re-rendering the parent component when the parent's state changes.
In this example, componentWillReceiveProps is never called.
Thank You!
Parent Component
export default class Parent extends Component {
constructor(props) {
super(props);
this.state = {
myValue: 'hello'
}
}
shouldComponentUpdate(nextProps, nextState) {
return false;
}
myFunction() {
this.setState(prevState => {
return {myValue: 'world'};
});
}
render() {
return (
<View>
<Button onPress={myFunction} title="Learn More"/>
<Child myText={this.state.myValue}/>
</View>
);
}
}
Child Component
export default class Child extends Component {
constructor(props) {
super(props);
}
componentWillReceiveProps(nextProps) {
console.log('This Is Never Called');
}
render() {
return (
<View>
<Text>{this.props.myText}</Text>
</View>
);
}
}
There is no way to do what you are proposing explicitly. When you define:
shouldComponentUpdate(nextProps, nextState) {
return false;
}
are telling Parent never to rerender after its initial render. However the passing of props to Child (and therefore the impetus for Child to rerender) happens inside the render method of Parent. So when you block rerending on Parent you are also blocking rerendering on all children of Parent.
There is, however, no need to block rerendering on Parent because React will modify the DOM as little as possible, so you will only see changes in parts of parent that need to be modified (due to a change of state). As long as all the props being passed to the other children of Parent (other than Child that is) remain unchanged, only Child will be modified in a Parent.render call.
Basically React already handles what you are trying to do.
In order to re-render child component with new props, parent component has to be re-rendered. There are generally no reasons to not re-render parent component in this situation. React was designed to do this efficiently and reuse existing DOM elements on re-render where possible.
The alternative approach is to make child component re-render its children and make parent component trigger the update somehow. This can be done with refs, for instance:
export default class Parent extends Component {
state = {
myValue: 'hello'
}
childRef = React.createRef();
myFunction = () => {
this.childRef.current.setText('world');
}
render() {
return (
<View>
<Button onPress={this.myFunction} title="Learn More"/>
<Child ref={this.childRef} myText={this.state.myValue}/>
</View>
);
}
}
And child component maintains its own state:
export default class Child extends Component {
static getDerivedStateFromProps({ myText }, state) {
return {myText, ...state};
}
setText(myText) {
this.setState({ myText });
}
render() {
return (
<View>
<Text>{this.state.myText}</Text>
</View>
);
}
}
Here's a demo.
This is acceptable solution but it results in less straightforward design. 'Dumb' Child like in original code is a preferable way to do this which shouldn't be changed for optimization reasons in general. If there are problems with re-rendering Parent children, they possibly should be addressed in another way.
I'm trying to understand how a child component can change its parents' state and realize that the only examples in which I am able to successfully accomplish this (and the only examples I see online) deal with a callback being passed from a parent to a child that is then linked to an event (onClick, onChange etc..) in the child. Thus, can a child component only change it's parents' state if the child uses an event to call the inherited callback?
This works:
class Child extends React.Component{
handleClick(){
console.log('pressed')
this.props.message('Hi mom!')
}
render(){
return (<button onClick={this.handleClick.bind(this)}>Prese Me</button>)
}
};
class Parent extends React.Component {
constructor(props){
super(props)
this.state = {
messageFromChild: '',
}
this.callBackFromParent = this.callBackFromParent.bind(this);
}
callBackFromParent(dataFromChild){
this.setState({messageFromChild: dataFromChild})
}
render(){
return (
<div>
<h2>Message from Child is:</h2>
<h2>{this.state.messageFromChild}</h2>
<Child message={this.callBackFromParent}/>
</div>
)
}
}
But this leads to in infinite loop:
class Child extends React.Component{
render(){
this.props.message('Hi Mom')
return(
<h2>Dummy message from child</h2>
)
}
};
class Parent extends React.Component {
constructor(props){
super(props)
this.state = {
messageFromChild: '',
}
this.callBackFromParent = this.callBackFromParent.bind(this);
}
callBackFromParent(dataFromChild){
this.setState({messageFromChild: dataFromChild})
}
render(){
return (
<div>
<h2>Message from Child is:</h2>
<h2>{this.state.messageFromChild}</h2>
<Child message={this.callBackFromParent}/>
</div>
)
}
}
You don't necessarily need to use the functions as event handlers, but calling it directly on render would cause the parent component to setState immediately, which would result in another render of the Child component, and the loop continues. You could e.g. set a timeout in componentDidMount of the Child and it will work fine.
I tried to build a image upload tool, every child component have there own upload button.
Is there the way to let the upload function control by parent component?
following the code:
Child Component
class Child extends Component{
constructor(props){
super(props)
this.state={
imageUrl: 'base64'
}
}
componentDidMount(){
this.setState({imageUrl: this.props.image})
}
handleUpload(){
axios.post(this.state.imageUrl);
}
render(){
return(
<div>
<img src={this.state.imageUrl}/>
<button onClick={this.handleUpload.bind(this)}></button>
</div>
)
}
}
Parent Component
class Parent extends Component{
constructor(props){
super(props)
this.state={
imageFiles: [...image]
}
}
componentDidMount(){
}
render(){
return(
<div>
{
this.state.imageFiles.map(image=>{
return(
<Child image={image}/>
)
})
}
</div>
)
}
}
I know how to access the parent component function to child component by this way <child handle={this.handle.bind(this)}/> in the parent component.
Is there some method to let parent component functions can trigger all the child component?
You could move handle function in the parent component, then pass it to the child component like:
<Child image={image} onClickUpload={this.handleUpload}/>
Here is the same question
Make a ref for a child component and then call it within parent's function.
I am working on React application and making something like a framework where I have a wrapper component some thing like this.
class FrameworkComponent extends React.Component {
someFunction() {
// send data to child data using childs function
// something like this.some.thing.childFunction("mydata");
...
}
render() {
return (
<div>
<div><button onClick={this.someFunction}>Click me</button></div>
<div>{this.props.child}</div>
</div>
)
}
}
and using it like this :
class SecondComponent extends React.Component {
childFunction(dataRecived) {
alert(dataRecived);
}
render() {
return <div>Hello world</div>;
}
}
import FrameworkComponent from '../FrameworkComponent';
import SecondComponent from '../SecondComponent';
class OtherComponet extends React.Component {
render() {
return (
<div>
<FrameworkComponent>
<div><SecondComponent /></div>
</FrameworkComponent>
</div>
)
}
}
So here I want child's component receive data from parent wrapper component either by updating its child props : componentWillReceiveProps() or calling its child method.
Your best bet would be to use HOC - Higher - https://reactjs.org/docs/higher-order-components.html
I am attempting to change the state within a child component every time I call a function in it's parent component. How would I go about doing this? For Example,
class ParentComponent extends Component {
function onClick(){
// some function here to change child components state
}
render(){
return (
<div>
<ChildComponent />
<button onClick={this.onClick.bind(this)}>
</div>
)
}
class ChildComponent extends Component {
constructor(props){
super(props)
this.state = {
MyState: 1
}
}
render(){
return(
<div>
{this.state.MyState}
</div>
)
}
}
According to my understanding you are trying to achieve this:
class ParentComponent extends Component {
constructor(props){
super(props)
this.state = {
MyState: 1
}
}
function onClick(){
this.setState({MyState:this.state.MyState + 1})
}
render(){
return (
<div>
<ChildComponent sendToChild={this.state.MyState}/>
<button onClick={this.onClick.bind(this)}>
</div>
)
}
class ChildComponent extends Component {
render(){
return(
<div>
{this.props.MyState}
</div>
)
}
}
Call setState in your onClick handler -- this causes a rerender in the ParentComponent as well as any child component (unless a component returns false in shouldComponentUpdate, but you don't have this function implemented). However your child component will visually not change even when rerendered currently since it has no props.
Not sure what you want to achieve exactly, but if you were to move the state MyStatefrom ChildComponent to ParentComponent and pass MyState as a prop to ChildComponent, and in the onClick handler call setState and increment MyState then the ChildComponent would visually update.
Either put your onClick handler in the child component, lift the state up or pass the onClick through props.
What are you trying to accomplish?