How to get props in compononentDidMount() of child component - javascript

I am trying to pass a parameter from the parent component to the child's component's ComponentDidMount() method. I am only able to receive the props inside the render() of the child component and I am not able to pass it to the
ComponentDidMount() method.
Parent Component - Provider.js
export default class Provider extends Component {
constructor(props) {
super(props);
this.state = {
carePlan: "",
patID: ""
};
}
async componentDidMount() {
this.setState({
carePlan: this.cp
patID: this.props.location.state.id
});
console.log(this.state.patID);
}
render() {
return (
<div>
<Layout>
{!this.state.cp ? (
<AddCarePlan patID={this.state.patID} />
) : (
<div className="carePlan">
<DisplayCarePlan cp={this.state.carePlan} />
</div>
)}
</Content>
</Layout>
</div>
);
}
}
Child Component - AddCarePlan.js
class AddCarePlan extends Component {
constructor(props) {
super(props);
}
async componentDidMount() {
const patientID = this.props.patID;
console.log(patientID) // does not show ID
}
render() {
const patientID = this.props.patID;
console.log(patientID) // shows ID
return (
<div>
<h1> Add Care Plan </h1>
</div>
);
}
}
export default AddCarePlan;

You should remove keyword async before lifecycle methods in your components. As I can tell you are not using await nowhere inside of them and + React is not design to use them with async await functions. Even if you want to use componentDidMount to do some data fetching you should not use async since when data arrives, then() method on data fetching wil trigger component rerendering.
Try removing async from your code.

what about try to this?
{!this.state.cp ? (
this.state.patID ? <AddCarePlan patID={this.state.patID} /> : ''
) : (
<div className="carePlan">
<DisplayCarePlan cp={this.state.carePlan} />
</div>
)}

export default class Provider extends Component {
constructor(props) {
super(props);
this.state = {
carePlan: "",
patID: props.location.state.id
};
}
async componentDidMount() {
this.setState({
carePlan: this.cp
});
console.log(this.state.patID);
}
render() {
return (
<div>
<Layout>
{!this.state.cp ? (
<AddCarePlan patID={this.state.patID} />
) : (
<div className="carePlan">
<DisplayCarePlan cp={this.state.carePlan} />
</div>
)}
</Content>
</Layout>
</div>
);
}
}
try this way
this.state = {
carePlan: "",
patID: ""
};
async componentWillMount() {
this.setState({
patID: this.props.location.state.id
});
}
or try changing lifecycle

Related

in reactjs want to update parent state based on child state?

In reactjs I want to update parent state based on child state.
My parent component in Login.
I want child state in Login component role function
//this function to show link //
function GetLink(props) {
const { role } = props
let admin = <Link to='/Admin'>Admin</Link>
let f = <Link to='/Finance'>Finance</Link>
let s = <Link to='/Sales'>Sales</Link>
switch (role) {
default:
case "admin": return (
<>
{admin}
{f}
{s}
</>
)
case "finance": return (
<>
{f}
{s}
</>
)
case "sales": return (
<>
{s}
</>
)
}
}
//this is the parent component //
class Login extends Component {
constructor(props) {
super(props);
this.state = {
role: ""
}
}
//want this state to be update when child state is updated
role = () => {
this.setState({ role: });
}
render() {
return (
<>
{ this.state.role === "admin" }
<GetLink role={localStorage.getItem("role")} />
</>
);
}
}
now this is my child component where the state is updating in componentDidMount
//this is child component //
//the state is updating in this component //
class Sales extends Component {
constructor(props) {
super(props);
this.state = {role: "" }
}
componentDidMount() {
if (localStorage.getItem("role") === null) {
this.props.setState({ role: localStorage.setItem('role', 'sales') })
}
}
logout() {
localStorage.removeItem('role');
}
render() {
return (
<>
<h1>Sales</h1>
<button onClick={this.logout}>logout</button>
</>
);
}
}
export default Sales;
can anyone help me out with this problem?
I think it is the best way that you send a function as props.
<GetLink role={this.role} />

How to fire a function in child from parent in react?

My React app has three components. Two of them are child components and the other is parent. I need to pass a data (projectId) from one child component to the other child through the parent component and after receiving the data, fire a function. As my example, I'm sending projectId from ChildOne to Parent and then send projectId from Parent to ChildTwo. ChildTwo has a function called setProject(projectId) and I need to fire it once the projectID is received. The problem is I can't get the function getProjectId fired in ChildTwo by clicking on the button in ChildOne. I also tried with componentDidMount and componentWillReceiveProps which are not working for me. How can I do this?
Here what I tried
ChildOne :
class ChildOne extends React.Component {
constructor(props) {
super(props);
this.state = {
projectId: 3,
};
}
sendProjectId = (projectId) => {
this.props.sendId(projectId)
}
render() {
return(
<button onClick={() => this.sendProjectId(this.state.projectId)}>
Click
</button>
)
}
}
Parent:
class Parent extends React.Component {
constructor(props) {
super(props);
this.state = {
projectId: '',
};
}
getId = (proId) => {
this.setState({
projectId : proId
})
}
render() {
return(
<div>
<CildOne sendId={this.getId} />
<CildTwo sendOneId={this.state.projectId} />
</div>
)
}
}
ChildTwo:
class ChildTwo extends React.Component {
constructor(props) {
super(props);
this.state = {
projectId: '',
};
}
getProjectId = (this.props.sendOneId) => {
//Do something with this.props.sendOneId
}
render() {
return(
<div></div>
)
}
}
This would depend on what ChildTwo wants to accomplish with the said data.
Case 1:
ChildTwo intends to fetch some data with the corresponding projectId and display it in the component. Then, you can easily fetch this data in the parent component and pass the data down as props.
class Parent extends React.Component {
constructor(props) {
super(props);
this.state = {
projectId: '',
dataForChildTwo: null,
};
}
getId = (proId) => {
this.setState({
projectId : proId,
dataForChildTwo: fetchData(proId)
})
}
render() {
return(
<div>
<CildOne sendId={this.getId} />
<CildTwo data={this.state.dataForChildTwo} />
</div>
)
}
}
Case 2:
ChildTwo intends to make some change to something inside it when projectId changes. Then you can use componentDidUpdate hook to see if prop changed and respond to it.
class ChildTwo extends React.Component {
constructor(props) {
super(props);
this.state = {
projectId: '',
};
}
getProjectId = (this.props.sendOneId) => {
//Do something with this.props.sendOneId
}
componentDidUpdate(prevProps) {
if(this.props.projectId!==prevProps.projectId) {
// do something
}
}
render() {
return(
<div></div>
)
}
}
Case 3:
If none of the above cases work for you, then you can manually reload the complete component when the projectId changes using a key attribute:
<CildTwo key={this.state.projectId} sendOneId={this.state.projectId} />
Note: This reloads the whole component quite unnecessarily.
You did a mistake in getProjectId function of ChildTwo component.
Your function cannot receive anything as a parameter from prop.
So, your function should look like:
getProjectId = (sendOneId) => {
//Do something with this.props.sendOneId
}
Then you should use componentWillReceiveProps like this:
componentWillReceiveProps(nextProps) {
if (this.props.sendOneId !== nextProps.sendOneId) {
this.getProjectId(nextProps.sendOneId);
}
}
Here is a working codesandbox example that I created to fix your problem:
https://codesandbox.io/s/5v4rn7qnll
You should probably use componentDidUpdate with a condition to check to see whether the projectId in state needs to be updated when sendOneId changes. You can then use setStates callback to call getProjectId:
componentDidUpdate() {
const { projectId: currentProjectId } = this.state;
const { sendOneId: projectId } = this.props;
if (projectId !== currentProjectId) {
this.setState({ projectId }, () => this.getProjectId());
}
}
Full working example:
class ChildOne extends React.Component {
constructor(props) {
super(props);
this.state = {
projectId: 3,
};
}
sendProjectId = (projectId) => {
this.props.sendId(projectId)
}
render() {
return (
<button onClick={() => this.sendProjectId(this.state.projectId)}>
Click
</button>
);
}
}
class Parent extends React.Component {
constructor(props) {
super(props);
this.state = {
projectId: '',
};
}
getId = (projectId) => {
this.setState({ projectId });
}
render() {
return (
<div>
<ChildOne sendId={this.getId} />
<ChildTwo sendOneId={this.state.projectId} />
</div>
)
}
}
class ChildTwo extends React.Component {
constructor(props) {
super(props);
this.state = {
projectId: '',
};
}
componentDidUpdate() {
const { projectId: currentProjectId } = this.state;
const { sendOneId: projectId } = this.props;
if (projectId !== currentProjectId) {
this.setState({ projectId }, () => this.getProjectId());
}
}
getProjectId = () => {
console.log(this.state.projectId);
}
render() {
return (
<div></div>
);
}
}
ReactDOM.render(
<Parent />,
document.getElementById('container')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="container"></div>
Our you can try a functional component or hooks if you want to set some state
function ChildOne(props) {
const [projectId, setProjectId] = useState(3);
function sendProjectId(data){
props.sendId(projectId)
}
return(
<button onClick={() => sendProjectId(projectId)}>
Click
</button>
)
}
function ChildTwo(props) {
const [state, setState] = useState('')
function getProjectId(data) {
//Do something with this.props.sendOneId
console.log(`data here ${data}`)
return false;
}
getProjectId(props.sendOneId)
return (
<div>
</div>
)
}
function Parent(){
const [projectId, setProjectId] = useState('');
function getId(proId) {
setProjectId(proId)
}
return(
<div>
<ChildOne sendId={getId} />
<ChildTwo sendOneId={projectId} />
</div>
)
}

Logging of State of the Class Component

I am setting the state to an empty array, then calling a function to update the state of the component. When I log the state of the function, I am getting the empty array and the updated array at the same time.
Any reason why this is happening and how to only log the updated state.
Following is my code:
class App extends Component {
constructor(props) {
super(props);
this.state = {
videos: [],
};
YTSearch({ key: API_Keys, term: 'USA Top40' }, (videos) => {
this.setState({ videos });
});
}
render() {
return (
<div>
<SearchBar />
{console.log(this.state)}
</div>
)
}
}
Here is the console.log
You shouldn't return console.log in render method!
It's better your code should be:
class App extends Component {
constructor(props) {
super(props);
this.state = { videos: [] };
}
componentDidMount() {
YTSearch({ key: API_Keys, term: 'USA Top40' }, (videos) => {
this.setState({ videos });
});
}
componentDidUpdate(prevProps, prevState) {
const { videos } = this.state;
if(prevState.videos !== videos) {
console.log(videos);
}
}
render() {
return (
<div>
<SearchBar />
</div>
)
}
}
Also, you can place console.log outside of return:
render() {
console.log(this.state);
return (
<div>
<SearchBar />
</div>
)
}
Note: setState({}) is an async process more like a batch process that
runs asynchronously and doesn't block your UI. So you might not see
the updated results in the console right after you change the state.
I agree with #souroush's answer as it is recommended way of doing things. But one way to achieve what you're trying to do is make a function and console logging the state into it
logState = () =>{
console.log("State" , this.state)
}
render() {
return (
<div>
<SearchBar />
{this.logState()}
</div>
)}

React Handle interaction state between components

I have a simple component who show element onClick:
class MyComponent extends React.Component {
state = {
isVisible : false
}
render() {
const { isVisble } = this.state
return(
<div>
{isVisble ?
<div onClick={() => this.setState({isVisble: false})}>Hide</div> :
<div onClick={() => this.setState({isVisble: true})}>Show</div>}
</div>
)
}
}
I use this component three times in other component :
class MySuperComponent extends React.Component {
render() {
return(
<div>
<MyComponent />
<MyComponent />
<MyComponent />
</div>
)}
}
I need to pass isVisible at false for all other component if one of have isVisible to true
How to do that ?
Thanks
You should have your component controlled, so move isVisble to props and and then assign it from MySuperComponent.
Also pass MyComponent a callback so it can inform the parent if it wants to change the state.
You'd want some data structure to store that states.
https://codepen.io/mazhuravlev/pen/qxRGzE
class MySuperComponent extends React.Component {
constructor(props) {
super(props);
this.state = {children: [true, true, true]};
this.toggle = this.toggle.bind(this);
}
render() {
return (
<div>
{this.state.children.map((v, i) => <MyComponent visible={v} toggle={() => this.toggle(i)}/>)}
</div>
)
}
toggle(index) {
this.setState({children: this.state.children.map((v, i) => i !== index)});
}
}
class MyComponent extends React.Component {
render() {
const text = this.props.visible ? 'visible' : 'hidden';
return (<div onClick={this.props.toggle}>{text}</div>);
}
}
React.render(<MySuperComponent/>, document.getElementById('app'));
You can check your code here, is this what you want.
example

React.js: Why child component change parent state?

Why in this example child component changing parent component state? According to the Facebook(react.js) docs State is similar to props, but it is private and fully controlled by the component.
codepen example
class NameForm extends React.Component {
constructor(props) {
super(props);
this.state = {data: this.props.data};
}
handleChange(event) {
let updatedData = Object.assign({}, this.state.data);
updatedData[event.target.name][event.target.dataset.lang] = event.target.value;
this.setState({
data: updatedData
});
}
render() {
return (
<form>
{Object.keys(this.props.data.titles).map((l, index) =>
<input type="text" name="titles" data-lang={l} value={this.state.data.titles[l]} onChange={this.handleChange.bind(this)} />
)}
</form>
);
}
}
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
images: [{"titles": {"en": "deluxe1500x930.jpg"}
}],
count: 1
};
}
render() {
return (
<div>
{Object.keys(this.state.images).map((x,index) =>
<div>
{this.state.images[x].titles.en}
<NameForm data={this.state.images[x]} />
<button onClick={(() => {this.setState({ count: 2 })}).bind(this)}>test</button>
</div>
)}
</div>
)
}
}
Because you set the state with this.props.data.
the this.props.data came from the parent, therefore when it's changing so the state changes as well.
The solution is simple, just set the state with new value (copied from this.props.data) by using the spread operator instead of using the same reference.
this.state = {data: ...this.props.data};

Categories