I am new to Redux and currently using an API to fetch data. I am trying to pass the state from my parent to this.props.children using React.cloneElement. I think I am making a mistake when i am using React.cloneElement as the debugger is showing the state to be null when i pass it to the cloneElement function. Following is my parent render method:
render(){
const {courses} = this.state;
debugger;
let fn = (child) => {
return React.cloneElement(child, {
courses: courses
});
};
let childrenWithProps = React.Children.map(this.props.children, fn);
return (
<div>
<div className="container jumbotron jumbotron-fluid">
<h1>CoursesPage</h1>
<p>This page adds and lists all the courses</p>
<Link to="/courses/courseslist">
<Button color="primary">Course Listing</Button>
</Link>
</div>
{childrenWithProps}
</div>
);
}
From the Console, i can fairly assume it is calling the children correctly, but passing null value in the courses. However when i simply pass <CourseList courses={courses} /> it correctly assumes the state. So where am i exactly going wrong?
I get the following error in the console:
Uncaught TypeError: Cannot read property 'map' of undefined
at CourseList (courseList.js:20)
at ReactCompositeComponent.js:305
at measureLifeCyclePerf (ReactCompositeComponent.js:75)
at ReactCompositeComponentWrapper._constructComponentWithoutOwner (ReactCompositeComponent.js:304)
at ReactCompositeComponentWrapper._constructComponent (ReactCompositeComponent.js:279)
at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:187)
at Object.mountComponent (ReactReconciler.js:45)
at ReactDOMComponent.mountChildren (ReactMultiChild.js:236)
at ReactDOMComponent._createInitialChildren (ReactDOMComponent.js:703)
at ReactDOMComponent.mountComponent (ReactDOMComponent.js:522)
..where courseList is the child component.
Much help appreciated.
Since you're passing in a variable from the Parent class to the child class CourseList you will need to use props instead
const {courses} = this.props;
Link to Documentation Components and Props
This might be what you want instead.
render(){
const {coursesList} = this.props;
return (
<div>
<div className="container jumbotron jumbotron-fluid">
<h1>CoursesPage</h1>
<p>This page adds and lists all the courses</p>
<Link to="/courses/courseslist">
<Button color="primary">Course Listing</Button>
</Link>
</div>
{coursesList}
</div>
);
}
Related
I have this on reactjs in a functional component:
const searchTitle = useRef();
<FormGroup className={'filterItems p-3 active'} ref={searchTitle}>
<div onClick={()=> handleTitleToggle()}>
</div>
</FormGroup>
And want to toggle class on FormGroup via click on div.
const handleTitleToggle = () => {
searchTitle.current.classList.toggle('active')
}
But give me error:
TypeError: Cannot read properties of null (reading 'classList')
But if I use ref on div, it works fine, any idea?
<div ref={searchTitle} onClick={()=> handleTitleToggle()}>
</div>
if you are using MUI FormGroup Component be sure that it accept ref
and when you have chain of props on you object use optional chaining to avoid errors like this
searchTitle?.current?.classList?.toggle('active')
I am receiving the following errors
Warning: memo: The first argument must be a component. Instead received: object
Uncaught Error: Objects are not valid as a React child (found: object with keys {$$typeof, type, compare}). If you meant to render a collection of children, use an array instead.
They happen when I change this component
const Tab = () => onLastTab
? <AccountTab data={data.account} />
: <InfoTab data={data.info} />
To be this component, the only difference is the use of React.memo
const Tab = () => onLastTab
? React.memo(<TabOne data={data.one} />)
: React.memo(<TabTwo data={data.two} />)
Those components wrapped in React.memo are definately just functional components that look like
const TabOne = ({data}) => (
<div>
<div className='d-flex '>
...
</div>
</div>
)
Why would this be happening? What can I do to stop it?
As the error message explains, you need to pass component to the React.memo(), not an object. TabOne is obviously a component name but you already created an object of that component and passed it through the React.memo().
You need fix your code as follows:
const TabOne = ({data}) => (
<div>
<div className='d-flex '>
...
</div>
</div>
)
export default React.memo(TabOne)
const Tab = () => onLastTab
? <TabOne data={data.one} />
: <TabTwo data={data.two} />
Im looking into higher order functions and i dont really understand how this part works.
say i have the following function:
const withAdminWarning = WrappedComponent => {
return props => (
<div>
{props.isAdmin && <p>This is private info. Please dont share!</p>}
<WrappedComponent {...props} />
</div>
);
};
const Info = props => (
<div>
<h1>Info</h1>
<p>This info is: {props.info}</p>
</div>
);
const AdminInfo = withAdminWarning(Info);
ReactDOM.render(
<AdminInfo isAdmin={true} info="There are the details" />,
document.getElementById("app")
);
From my understanding of components, to access the props variable, you have to use either props, if its a stateless component, or this.props if it is a class component.
From where does the props come into play in the example above as i cant get access to it from the WrappedComponent or anywhere else apart from the return statement.
The Higher order Component returns a function which is a functional component. Am I right in thinking that foo(Info) means withAdminWarning(Info)?
So after calling withAdminInfo the AdminInfo Component looks basically like:
const AdminInfo = props => (
<div>
{props.isAdmin && <p>This is private info. Please dont share!</p>}
<div>
<h1>Info</h1>
<p>This info is: {props.info}</p>
</div>
</div>
);
I solve it with a simple flag like so:
I added a new flag property on the states object: loaded:false
I update the loaded value to true, when i get the data, like so:
helpers.getValues().then(results => this.setState({values:results.data,loaded:true}));
And finally, inside the render() i first check if the loaded==true and then i render the ChildComponent, like so:
{this.state.loaded == true ? <ChildComponent values={this.state.values} name="theodore"/> : ''}
I am making a simple code in React that gets data with Axios.
The data are returned to the client , so the communication is OK.
The problem is that I pass the results data to a child component , as props, and as soon as the child component loads it asks for the props.data but it is empty.
Below is the Parent component:
Inside the componentDidMount I call the axios to get the data and update the setState object.
Below, into the render function, I pass the results to the ChildComponent.
var ParentComponent = React.createClass({
getInitialState:function(){
return {
values:''
activeTab:0
}
},
componentDidMount:function(){
helpers.getValues().then(results => this.setState({values:results.data}));
},
render:function(){
return(
<div className='container'>
<div className="row">
<div className="col-sm-8 text-center" >
<h1>{pageTitle}</h1>
<Tabs activeKey={this.state.activeTab} onSelect={this.handleSelect} id="controlled-tab-example">
<Tab eventKey={tabs[0].key} title={tabs[0].name}>
Tab1
<ChildComponent1 values={this.state.values} test="ok"/>
</Tab>
<Tab eventKey={tabs[1].key} title={tabs[1].name}>Tab2</Tab>
</Tabs>
</div>
</div>
</div>
)
}
And here i show the ChildComponent(in a seperate js file).
Inside the componentDidMount I try to show the props but the object that gets it like:
{values:'',test:'ok'}
var ChildComponent = React.createClass({
componentDidMount:function(){
console.log(this.props);
},
render:function(){
return(
<div>
<ul>'nothing'</ul>
</div>
)
}
});
I guess that it is a delay issue, in which the chld component loads before the axios async returns the data from server
Any help from someone that has dealt with a similar situation would be appriciated, thanks.
Because you're passing this.state.movies, instead of this.state.values to the ChildComponent.
How you do it:
<ChildComponent1 values={this.state.movies} test="ok"/>
How it should be:
<ChildComponent1 values={this.state.values} test="ok"/>
I am trying to pass two argument using props in ImageText component.
I am not sure if it is right method or I have to create a map and then pass it.
import React, { PropTypes, Component } from 'react'
const ImageText = () => (
<div className="img-with-text">
<img className="img" src={props.imageUrl} />
<p className="txt">{props.imageText}</p>
</div>
);
export default ImageText;
Calling this component from another as follows
<ImageText imageUrl="/js.com" imageText="food"/>
But is throwing error as
Uncaught (in promise) ReferenceError: props is not defined
at ImageText
In your case issue with you are using "Arrow functions" which needs to pass params inside brackets
const ImageText = () => (
Should be
const ImageText = (props) => (
Now
let props = {
imageUrl:"/js.com",
imageText:""food""
}
<ImageText {...props} />
Access inside ImageText like
{props.imageUrl} or {props.imageText}
When you define your component like that, you need to pass your props as parameters to the anonymous function:
const ImageText = ({imageUrl, imageText}) => (
... rest of the code ...
);
When using a functional component (when you don't use a class) you must pass the props as an argument into to the function.
You can pass as many props add you need into a component.
const ImageText = (props) => (...
If using a standard component (as a class) you would call a prop with
this.props
Passing down multiple props in reactJS can be done using either of following ways:
// in App.js
<Modal post= {postProps} user={userDetails}/>
// in Modal.js
const Modal = (props) => {
const title = props.post.title
const username = props.user.username
// rest of the code..
}
in above example props (in Modal.js) forms an object with keys named post and user, thus you can access them like objects.
Another way would be:
// in App.js
<Modal post={postProps}/>
// in Modal.js
const Modal = ({post}) => {
const title = post.title
// rest of the code..
}
in this example post object has been imported explicitly in Modal.js
Final Remark : With first approach it gets very clear looking at your code that what has been passed down as props from parent element and might be clear to read.
While with second approach i argue that, it is better to use in scenarios where its just one prop to pass, since you don't have to write props. everytime
you are passing the props to dump component. it's not react component. pass the props to dump as function argument.
> import React, { PropTypes, Component } from 'react'
>
> const ImageText = ({imageUrl, imageText}) => (
> <div className="img-with-text">
> <img className="img" src={imageUrl} />
> <p className="txt">{imageText}</p>
> </div> );
>
> export default ImageText;
Creating:
const ImageText = ({ imageUrl, imageText }) => (
<div className="img-with-text">
<img className="img" src={imageUrl} />
<p className="txt">{imageText}</p>
</div>
);
export default ImageText;
Using; when you have already defined imageUrl and imageText somewhere before the return keyword:
<ImageText {...{imageUrl, imageText}}