This question already has answers here:
JS/ES6: Destructuring of undefined
(8 answers)
Closed 1 year ago.
I have a small project, to fetch image from unsplash, even I check many times, I still have one problem in my code, I am running my code, but it is always give this error, but I don't get it. Any idea will be appreciated.
Mainboard.js
import React from 'react';
import styled from 'styled-components';
import Pin from './Pin';
function Mainboard(props) {
let { pins } = props;
return (
<Wrapper>
<Container>
{pins.map((pin, index) => {
let {urls} = pin;
return <Pin key={index} urls={urls}/>
})}
</Container>
</Wrapper>
)}
export default Mainboard;
Pin.js:
import React from 'react';
import styled from 'styled-components';
function Pin(props) {
let { urls } = props;
return (
<Wrapper>
<Container>
<img src={urls?.regular} alt="pin"/>
</Container>
</Wrapper>
)}
export default Pin;
I don't think the main issue is destructing from an undefined object (this is only a symptom), but more that you have "holes" in your data, i.e. your array has undefined elements in it.
If there is an undefined element in your pins array then perhaps you should filter them first before mapping. A quick way is to apply a Boolean constructor against the truthy defined values and the falsey undefined values, i.e. arr.filter(Boolean).
function Mainboard({ pins }) {
return (
<Wrapper>
<Container>
{pins.filter(Boolean).map((pin, index) => {
const {urls} = pin;
return <Pin key={index} urls={urls}/>
})}
</Container>
</Wrapper>
);
}
Of course you should try to ensure your data array is properly maintained in the first place so "holes" aren't introduced. If you add how Mainboard is rendered, what the props values are that are passed to it we may be better able to help optimize.
Related
This question already has answers here:
Access <a> tag inside onclick function in React
(1 answer)
Why React Function Component's "this" is undefined
(2 answers)
Closed 9 months ago.
I'm still beginner in ReactJS and JavaScript and I'm having trouble using this.
I'm rendering a list of properties and when I do onMouseOver I'd like to get the element I'm hovering over with this. But it's returning undefined.
Can you tell me why I'm getting this error?
Here's my code I put into codesandbox.io
Thank you very much in advance.
import React from "react";
import "./styles.css";
import Property from "./components/Property";
import { mock } from "./data/mock";
export default function App() {
const [data] = React.useState(mock.data.dora.exploreV3.sections[2].items);
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
{data.map((item) => (
<Property key={item.listing.id} item={item} />
))}
</div>
);
}
import React from "react";
const Property = ({ item }) => {
return (
<div
style={{
padding: "5px 0",
cursor: "pointer"
}}
onMouseOver={() => console.log("item: ", this)}
>
{item.listing.name}
</div>
);
};
export default Property;
The reason your code does not work as you expect is because this is not bound to the element during rendering. You need to access the element using the MouseEvent target. Your Property component should look like this:
import React from "react";
const Property = ({ item }) => {
return (
<div
style={{
padding: "5px 0",
cursor: "pointer"
}}
onMouseOver={(event) => console.log("item: ", event.target)}
>
{item.listing.name}
</div>
);
};
export default Property;
Alternatively, you could use React's useRef to do this. Here's a good article explaining how to implement that: https://linguinecode.com/post/get-current-element-react-onmouseover-or-onmouseenter
Fat arrow functions are not able to access "this" keyword.
Try updating the function as a regular function.
This might be helpful : https://www.section.io/engineering-education/how-to-use-javascript-arrow-functions-and-this-keyword/
I'm very green at react, and I'm trying to learn the library by messing around a bit.
I'm having problems passing an object to another component.
Ive created an array of objects that holds 2 string variables, 1 function and 1 int.
I'm trying to populate this inside a Grid container(Material UI framework).
When I pass the object to the other react component, it arrives as undefined. Ive tried to check if I'm passing a valid object by logging it to the console first, and it is valid.
I've also tried to refer to the properties in the component that receives the object, but the browser console throws Uncaught TypeError: Cannot read properties of undefined (reading 'person').
Does anyone know why it is being sent as undefined?
PersonList.js:
const personListe = [
{
firstName:'testFirstname',
lastName:'testLastName',
getFullName:function()
{
return `${this.firstName} ${this.lastName}`
},
age:28
}
]
export default function PersonList() {
return (
<>
<Grid container spacing={3}>
{personListe.map((person) => {
return(
<Grid item xs={3} key={person.firstName}>
<PersonCard person={person} />
</Grid>
)
})}
</Grid>
</>
);
}
PersonCard.js:
export default function PersonCard({props})
{
return (<>
{console.log(props)}
</>)
}
The PersonCard Component recieves props object which includes the person object inside it.
export default function PersonCard({person})
{
return (
<>
{console.log(person)}
</>
)
}
OR
export default function PersonCard(props)
{
return (
<>
{console.log(props.person)}
</>
)
}
Been stuck on debugging this for quite a while. I'm trying to have a group of items change onClick but with the use of transform but 'style' is undefined. I've also included the Card component functions. Help would be greatly appreciated
import React,{useRef} from 'react';
import { Card } from '../components';
import { CardItemContainer } from './card-item';
export function CardContainer()
{
const listRef=useRef()
const handleClick=(direction)=>
{
if(direction==="left")
{
listRef.current.style.transform=`translate(230)`
}
}
return(
<Card>
<Card.ListTitle> Continue to watch</Card.ListTitle>
<Card.Wrapper >
<Card.ArrowSliderLeft onClick={()=>handleClick('left')}/>
<Card.List ref={listRef}>
<CardItemContainer index={0}/>
<CardItemContainer index={1}/>
<CardItemContainer index={2}/>
<CardItemContainer index={3}/>
<CardItemContainer index={4}/>
<CardItemContainer index={5}/>
<CardItemContainer index={6}/>
</Card.List>
<Card.ArrowSliderRight onClick={() => handleClick("right")}/>
</Card.Wrapper>
</Card>
)
}
Card Components
import {ArrowBackIosOutlined,ArrowForwardIosOutlined} from "#material-ui/icons";
import React, {} from 'react';
import {
Container,
List,
ListTitle,
Wrapper,
ArrowSliderLeft,
ArrowSliderRight
} from './styles/card';
export default function Card({ children, ...restProps }) {
return <Container {...restProps}>{children}</Container>
}
Card.ListTitle=function CardListTitle({children,...restProps})
{
return <ListTitle{...restProps}> {children} </ListTitle>
}
Card.Wrapper=function CardWrapper({children,...restProps})
{
return <Wrapper{...restProps} > {children} </Wrapper>
}
Card.List=function CardList({children,...restProps})
{
return <List{...restProps} >{children}</List>
}
Card.ArrowSliderLeft = function HeaderArrowBackIosOutlinedSymbol({...restProps })
{
return <ArrowSliderLeft {...restProps }>
{/*id allows me to style the icon directly */}
<ArrowBackIosOutlined id="sliderLeft"/>
</ArrowSliderLeft>
}
Card.ArrowSliderRight = function HeaderArrowForwardIosOutlinedSymbol({...restProps}) {
return (
<ArrowSliderRight {...restProps}>
<ArrowForwardIosOutlined id="sliderRight"/>
</ArrowSliderRight>
);
};
Ignore:
Been stuck on debugging this for quite a while. I'm trying to have a group of items change onClick but with the use of transform but 'style' is undefined. I've also included the Card component functions. Help would be greatly appreciated
Function components like CardList don't have a ref property, only class components or DOM elements do.
You haven't posted List component's implementation, but let's assume it has a <ul> tag, and that is what you eventually need to manipulate its .style.transform
CardList >>> List >> ul (this is the element you need to pass the ref)
To pass the listRef all the way to ul from CardList you need to use the forwardRef technique.
Card.List=React.forwardRef(function CardList (props,ref)
{
const {children,...restProps} = props
return <List{...restProps} ref={ref} >{children}</List>
})
the List component itself :
const List = React.forwardRef(function (props,ref) {
return <ul ref={ref}>
... the implementation of your List
Now you can pass listRef in here and it goes down the chain:
<Card.List ref={listRef}>
Side Note: taking from Drew Reese's comment on this answer, since CardList is just transfering the same props from a parent component to List, you can simply assign List to Card.List, then only one step of ref forwarding would be enough:
Card.List = List // CardList component isn't used anymore.
The same thing could work for Card.ListTitle and Card.Wrapper:
Card.ListTitle=ListTitle
Card.Wrapper=Wrapper
I too have just faced this same issue, and have tried to get my code working again. Checking similarity between your given code and my erroneous code snippet helped me fix the error.
Strangely, I have faced this error with a JSX multi-line comment in place after my element (MUI <Snackbar> element, in my case).
Error(s):
My code snippet looked something like:
<Snackbar open={snackbarOpen} autoHideDuration={5000} onClose={()=>setSnackbar(false)} > {/* My Comment Here */}
<>...</>
</Snackbar>
Quite similar place of JSX comment as your Card Component
Card.ArrowSliderLeft = function
...
return <ArrowSliderLeft {...restProps }>
{/*id allows me to style the icon directly */}
<ArrowBackIosOutlined ... />
</ArrowSliderLeft>
Removing just the comment part {/* */} immediately following an opening tag worked for me.
So, try removing your JSX comment or placing it elsewhere,and see if it helps.
Sharing it here just for my and others future reference. :)
I have the Functional React component defined below:
import React from 'react';
import Cell from './FeedCell';
import PropTypes from 'prop-types';
const Feed = (props) => {
return props.arr.map((type, index) => {
return (<Cell />)
})
};
I am getting the error:
Feed(...): A valid React element (or null) must be returned. You may have returned undefined, an array or some other invalid object.
I feel like this should be obvious but I have tried the solutions presented online but I am missing something.
You are currently returning an array, but you must return a proper React element.
You can wrap your array in a React.Fragment if you don't want a wrapping element in the DOM.
const Feed = (props) => {
return (
<React.Fragment>
{props.arr.map((type, index) => <Cell />)}
</React.Fragment>
);
};
You need to wrap your array in some element
If you don't want to wrap your FeedCells in an actual element, you can use React.Fragment instead:
const Feed = (props) => {
return (
<React.Fragment>
{ props.arr.map((type, index) => <Cell />) }
</React.Fragment>
);
};
More information here:
https://reactjs.org/docs/fragments.html
Can you add more information? - FeedCell code and the parent of Feed.
Try console logging the props and check if props.disputesToRender actually exists or has value in all your render calls.
Check if FeedCell actually returns html or a component that returns an html.
You should also add a <div> or <React.Fragment> to enclose your return method. Since there should always be a single parent on returns.
I know there are many answers out there for this issue but I couldn't find one that exactly solved my problem. I am getting the following error : Warning: Each child in an array or iterator should have a unique "key" prop. Check the render method of QuestionItem. See https://fb.me/react-warning-keys for more information.
I am setting a key for the component but I can't get the warning to go away.
Main component :
renderData() {
return this.state.data.map((data) => {
return (
<QuestionItem key={data._id} data={data} delete={this.deleteItem} edit={this.editItem} />
)
})
}
QuestionItem component :
import React, { Component, PropTypes } from 'react';
import Card from 'material-ui/lib/card/card';
import CardActions from 'material-ui/lib/card/card-actions';
import CardHeader from 'material-ui/lib/card/card-header';
import CardMedia from 'material-ui/lib/card/card-media';
import CardTitle from 'material-ui/lib/card/card-title';
import FlatButton from 'material-ui/lib/flat-button';
import CardText from 'material-ui/lib/card/card-text';
import Delete from 'material-ui/lib/svg-icons/action/delete';
import ModeEdit from 'material-ui/lib/svg-icons/editor/mode-edit';
import IconButton from 'material-ui/lib/icon-button';
import Button from '../UI/Button';
class QuestionItem extends Component {
renderTags() {
return this.props.data.tag.map((tag) => {
return (
<FlatButton label={tag} />
)
})
}
renderCompany() {
return this.props.data.company.map((company) => {
return (
<FlatButton label={company} />
)
})
}
edit = () => {
this.props.edit(this.props.data);
}
delete = () => {
this.props.delete(this.props.data._id);
console.log(this.props.data._id);
}
render() {
return (
<Card style={{margin: 50}}>
<CardTitle title={this.props.data.text} />
<CardText>
{this.props.data.answer}
</CardText>
<CardActions>
{ this.renderTags() }
{ this.renderCompany() }
<IconButton onClick={this.delete} style={{float: 'right'}}>
<Delete />
</IconButton>
<IconButton onClick={this.edit} style={{float: 'right'}}>
<ModeEdit />
</IconButton>
</CardActions>
</Card>
)
}
}
export default QuestionItem;
What am I missing here?
Well you'll need to log out the data._id and verify that they are all unique. Or you can do this:
renderData() {
return this.state.data.map((data, index) => {
return (
<QuestionItem key={index} data={data} delete={this.deleteItem} edit-{this.editItem} />
);
});
}
As the other answer pointed out, the other calls to map that go to a render need to set the key prop too to a unique value.
So these:
renderTags() {
return this.props.data.tag.map((tag) => {
return (
<FlatButton label={tag} />
)
})
}
renderCompany() {
return this.props.data.company.map((company) => {
return (
<FlatButton label={company} />
)
})
}
Should become:
renderTags() {
return this.props.data.tag.map((tag, index) => {
return (
<FlatButton key={index} label={tag} />
);
});
}
renderCompany() {
return this.props.data.company.map((company, index) => {
return (
<FlatButton key={index} label={company} />
);
});
}
Note we are using index which is the array index. It is basically like a synthetic identifier in SQL. If what you're actually rendering has unique identifiers already, it is better to use those! For example, the key prop for a tag could be just the tag -- the string itself. The key prop supports multiple types:
react - nodes-and-elements:
key : string | boolean | number | null,
So if your tags are unique (I would expect them to be but obviously don't want to assume), you could do this:
renderTags() {
return this.props.data.tag.map((tag) => {
return (
<FlatButton key={tag} label={tag} />
);
});
}
You might consider doing instead something like (tag || '').toLowerCase().replace(' ', '_') however I think React is already doing some manipulation there (besides potentially character case). So just passing the tag itself should be good! You can inspect the DOM to see data-reactid if you're not running a version that got rid of it (I think 0.15 gets rid of it). The React developer tools might let you inspect the key with 0.15.
Update
I do not recommend using the array index as the key. It causes subtle bugs. To see this in action, make an array of objects, render them using the array index and then mutate the array by removing say the 2nd element (and ensure React renders again). Now the indexes don't correspond to the same objects. My recommendation is to always set a key to a unique value. During development, it might be best not to set a key until you find one rather than using the array index because then the errors on the console will remind you to fix this before deploying/committing your change.
In renderTags() and renderCompany() you have iterators with no keys.