react.js props and state inside multilevel components - reactjs

I have one app having component structure like below.
Component App Main parent which loads header in all components using {this.props.children}
Component Header
Component Home
Component Dashboard
Component Data
Component DataLoad
App contains Header in render passing some state variables.
Home contains Dashboard which has actions to update the state variables of App to update the Header.
Data contains DataLoad also from here i need to update the state variable of App to update the Header.
For example my App is like
import React from 'react';
import Header from './Header.jsx';
class App extends React.Component {
constructor(props) {
super();
this.state = {
show : '1',
}
this.showHide = this.showHide.bind(this);
}
showHideSearch() {
this.setState(prevState => ({
show: prevState.show == '1' ? '0' : '1',
}));
}
render() {
return (
<div>
<Header show={this.state.show}/>
{this.props.children}
</div>
)
}
}
export default App;
import React from 'react';
import Dashboard from './Dashboard.jsx'
class Home extends React.Component {
constructor(props) {
super();
this.showHide = this.showHide.bind(this);
}
showHide() {
tried this but not working
//this.props.showHideSearch();
}
render() {
return (
<div>// this props show not going to dashboard component
<Dashboard show={this.props.show} showHide= {this.showHide.bind(this)}/>
</div>
)
}
}
export default Home;

If I am understanding your question right, you are wanting to pass your this.showHideSearch function from your App component to its the component in this.props.children - your Home component.
This is easily accomplishable using:
React.cloneElement(this.props.children, {showHideSearch: this.showHideSearch});
Put that in place of where you have this.props.children.
Source - https://stackoverflow.com/a/35102287/6621973
Edit: To update a parent's state, simply pass down a function setting the state from parent to child. There are several examples if you Google "react change parent state", for example: How to update parent's state in React?

Related

Can a child component render its parent content only?

I'm extending a parent component that is part of an SDK (AWS Amplify - SignIn), which I have no control over. I only need to make a small change where the input field data will be modified to be lowercase before it's passed to the authentication function.
import React from "react";
import { SignIn } from "aws-amplify-react";
export class CustomSignIn extends SignIn {
constructor(props) {
super(props);
this._validAuthStates = ["signIn", "signedOut", "signedUp"];
}
showComponent(theme) {
return (
<div>My child component that I don't need to render</div>
);
}
}
export default CustomSignIn;
This is more of a general question not specifically related to AWS Amplify, but I'd like to use the existing UI / rendering code from the parent — is there a way to simply display the parent's rendering content and not have any child content?
You can extend a component and use that components render function.
class ComponentFromThirdParty extends React.Component {
render() {
return <div>This is ComponentFromThirdParty</div>;
}
}
class MyComponent extends ComponentFromThirdParty {
componentDidMount() {
console.log(
"MyComponent was mounted and I render the same as ComponentFromThirdParty"
);
}
render() {
return super.render();
}
}
MyComponent will render this when mounted.
This is ComponentFromThirdParty

A Component changing its props?

So, I want my component to render only when I do it (eg. when it is clicked.) . I don't want it to re-render when its props changes.
So, my idea was to have the parent pass a wasClicked='true' prop, when it is clicked, which I change to 'false' once it is rendered and have a condition in the render body to only render when wasClicked is true.
How is this possible?
With class components, you can decide if you want to update component with a lifecycle method called shouldComponentUpdate. With a functional component, you can decide if the component should update with React.memo
That should be easy, lets say this is a simple component that only renders when wasClicked is true:
simpleComponent.js:
import react from "react";
const SimpleComponent = (props) => {
return <p> some text </p>;
};
export default SimpleComponent;
App.js;
import react from "react";
import SimpleComponent from "./simpleComponent.js";
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
wasClicked: false, //this is the state for wasClicked
};
}
//this is the function that changes wasClicked to true when the component is clicked
handleClick = () => {
this.setState({ wasClicked: true });
};
render() {
return (
<>
{this.state.wasClicked && ( //this will only render SimpleComponent when wasClicked is true
<SimpleComponent
onClick={this.handleClick}
wasClicked={this.state.wasClicked}
/>
)}
</>
);
}
}
export default App;
Hope this was helpful and clear, thanks

Extend React lifecycle hook (e.g add a print statement on every ComponentDidMount)

I want to add some behaviour on a given lifecycle hook of a React application.
For example, adding a console.log('Component is mounted') on every ComponentDidMount of all the components of an application, without having to define it in every one of them (as a decorator for example), sort of like a global extender of that method that adds some code to it. Like that: Extending Vue Lifecycle Hooks but for React.
Anyone has an idea on how to achieve that? Cheers!
You can use hoc. In the root app, apply the higher order component.
Example:
const withMountHOC = WrappedComponent => {
return class extends Component {
componentDidMount() {
console.log('mounted');
}
render() {
return <WrappedComponent {...this.props} />
}
}
}
export default withMountHOC;
In your app component:
const WrappedApp = withMountHOC(App);
ReactDOM.render(
WrappedApp,
document.getElementById('root')
);
Since the parent componentDidMount hook is called after child componentDidMount hook, the HOC componentDidMount will be applied in any nested level of the component.
You may also be interested to see this blog: Replacing Mixins in React.
create CustomComponent.js
import React, { Component } from 'react'
class CustomComponent extends Component {
constructor(props){
super();
}
componentDidMount(){
console.log('component is mounted');
}
render () {
return (
<div>
{this.props.children}
</div>
)
}
}
export default CustomComponent
Now create MyComponent.js that extends CustomComponent.js
import React, { Component } from 'react'
import CustomComponent from './CustomComponent'
class MyComponent extends CustomComponent {
render () {
return (
<div>
Hello from MyComponent
</div>
)
}
}
export default MyComponent;
now you see console , you have log : "component is mounted"
but if you write componentDidMonunt() inside MyComponent.js , you will get log from MyComponent.js

Link Props to State ReactJS

I'am using reactjs and Redux to transfer data from a page to another page,
in the first page i'am dispatching an action to save the values,
this works good
In the second page, I have a component using this saved values
so the this.props.values give me exactely the values
but in this component i have to use in the render part the this.state.values
Is there a way to link this.props.values to my this.state.values in my second page ?
Is there a way to link this.props.values to my this.state.values in my second page ?
If that's all you want, the best way to put props into state is in the constructor
class Component extends React.Componet {
constructor(props) {
super(props)
this.state = { values: props.values || [] } // [] or some default value
}
}
just make sure you handle the case where the props value changes using componentWillReceiveProps
componentWillReceiveProps (nextProps) {
if (!equals(this.props.values, nextProps.values)) {
this.setState({ values: nextProps.values })
}
}
equals is whatever you want it to be (==, lodash#deepEquals, etc)
You can use class like this or if you are writing in function style, pass props as argument and simply call in return as {props.values}
import React, {Component} from 'react';
class testSample extends Component {
constructor(props) {
super(props)
console.log(props.value); //check whether you are receiving values in browser console
this.state = { values: props.values }
}
render(){
return(
<div>{this.state.values} </div>
)
}
}
export default testSample
or you can directly access them like this instead assigning to state again.
import React, {Component} from 'react';
class testSample extends Component {
constructor(props) {
super(props)
console.log(props.value); //check whether you are receiving values in browser console
}
render(){
return(
<div>{this.props.values} </div>
)
}
export default testSample

Passing Props to Screens in React Native

I have started to learn React Native and as always begin by creating reusable components. I learnt how you can pass and access props while creating custom components.
I want to create a base screen in React Native, which has common properties and all screens in my app can set, like a title for example.
Below I'm creating a new Screen for the home page of my app
class APCComponent extends Component {
constructor(props) {
super(props);
}
render() { //dummy function, will always get overridden in the child
return (
<View />
);
}
}
export default class Home extends APCComponent {
//I somehow want to pass a string to the parent APCComponent
//and want APCComponent use it to set the Header of the navigation
constructor() {
super({ title: 'Home' });
}
//Right now the following works, but in case I use a different type of Navigation,
//I'll have to change all components. By just setting a string, I'm allowing my base
//component to display the header
static navigationOptions = { title: "Home" }; //from react-navigtion's StackNavigator
render() {
return <Button title="Sample Button" />;
}
}
Thanks
class BaseComponent extends Component {
render() {
return (){
<Header title={this.props.title} />
}
}
}
class HomeScreen extends Component {
render() {
return (){
<BaseComponent title='this is your home screen' />
}
}
}
where Header component is also a separate reusable component.
you need to pass props(in our case 'title') from the upper level component to base level components like the above example.
In the constructor of HomeScreen, props should be able to passed to BaseComponent through
constructor(props) {
super(props);
...
does it work for you?

Resources