TypeError: author is undefined - reactjs

creating react AuthorQuiz app
I have tow main file
1- AuthorQuiz.js
2- index.js
I have a problem with Turn component
AuthorQuiz.js
enter code here
function Turn({ author, books }) {
return (
<div className="row turn" style={{ backgroundColor: 'white' }}>
<div className="col-4 offset-1">
<img src={author.imageUrl} className="authorImage" alt="Author" />
</div>
<div className="col-6">
{books.map((title) => <p>{title}</p>)}
</div>
</div>);
}
function AuthorQuiz(turnData) {
return (
<div className="container-fluid">
<Hero/>
<Turn {...turnData}/>
<Continue/>
<Footer/>
</div>
);
}
index.js
enter code here
const authors = [
{
name: 'mark Twin',
imageUrl: 'images/authors/mark.jpg',
imageSource: 'google wiki',
books: ['The Advance of Finn']
}
];
const state={
turnData:{
author:authors[0],
books:authors[0].books
}
}
ReactDOM.render(<AuthorQuiz {...state}/>,
document.getElementById('root'));
but when I run my code I get an error
TypeError: author is undefined
Turn
C:/Users/HP/Desktop/React pro/authorquiz/src/AuthorQuiz.js:18

You should use {state.turnData} instead of {...state}.
Because the result of {...state} is like this: {turnData: {…}}
So { author, books } can't work correctly.

const state={
turnData:{
author:authors[0],
books:authors[0].books
}
}
<AuthorQuiz {...state}/>
Spreading the state over the AuthorQuiz is equivalent to:
<AuthorQuiz turnData={state.turnData}/>
But in the AuthorQuiz component:
function AuthorQuiz(turnData) {
return (
<div className="container-fluid">
<Hero/>
<Turn {...turnData}/>
<Continue/>
<Footer/>
</div>
);
}
function AuthorQuiz(turnData) {
...
<Turn {...turnData}/>
...
is equivalent to
function AuthorQuiz(props) {
...
<Turn turnData={
props.turnData
}}/>
...
So you need to add brackets to spread turnData instead of props:
function AuthorQuiz({ turnData }) {
...
<Turn { ...turnData}}/>
...

The AuthorQuiz component is getting the turnData variable as a prop. You should use the spread operator on the props.turnData variable instead.
function AuthorQuiz(props) {
return (
<div className="container-fluid">
<Hero/>
<Turn {...props.turnData}/>
<Continue/>
<Footer/>
</div>
);
}
The props in the AuthorQuiz component look like this:
{
turnData: {
author: { .. },
books: [ .. ]
}
}
Your Turn component wants the author and books props, so you could do this in your AuthorQuiz component.
function AuthorQuiz(props) {
return (
<div className="container-fluid">
<Hero/>
<Turn {...props.turnData} />
{/* or */}
<Turn author={props.turnData.author} books={props.turnData.books} />
<Continue/>
<Footer/>
</div>
);
}
You could also destructure the turnData prop in your component function directly. This makes it clear which props are being drilled down the Turn component without switching to multiple files.
function AuthorQuiz({ turnData: { author, books } }) {
return (
<div className="container-fluid">
<Hero/>
<Turn author={author} books={books} />
<Continue/>
<Footer/>
</div>
);
}

Related

Remove item from array react js

I'm having trouble with removing an object from an array. I have tried many options and nothing works.
Please help me solve this problem.
Thanks for your help
My array:
export const SavedList = [
{
word: 'hello',
translate: 'привет',
note: 'say say'
}
]
Remove callback (deletePost)
class Menu extends Component {
state = {
word: '',
translate: '',
note: '',
data: SavedList,
}
deletePost =(id)=>{
this.setState({
data : this.state.data.filter((el)=> el.id !== id)
})
}
render() {
return (
<div className="content">
<Routes>
<Route path="/" element={<Layout />}>
<Route path="saved" element={<Saved data={this.state.data} del={this.deletePost}/>}/>
</Route>
</Routes>
<div>
</div>
</div>
);
}
}
export default Menu;
here button delete with onClick
class Saved extends Component {
render() {
const sl = this.props.data.map((sl, id) => {
return (
<div className="saved-card" key={id}>
<div className="content">
<p>{id}</p>
<p>{sl.word}</p>
<p>{sl.translate}</p>
<p>{sl.note}</p>
</div>
<div className="btn-block">
<button
onClick={() => this.props.del(id)}
type="button"
className="delete-btn"
>
delete
</button>
</div>
</div>
);
});
return (
<div>
<h2>Saved list</h2>
<div className="saved-inner">
<div className="saved-list">{sl}</div>
</div>
</div>
);
}
}
export default Saved;
This issue is because el.id doesn't have any value in delete Post Function. That function also needs to have an ID variable, I have named it as i_di.
class App extends Component {
state = {
word: '',
translate: '',
note: '',
data: SavedList,
}
deletePost =(id)=>{
this.setState({
data : this.state.data.filter((el, i_di)=> i_di !== id )
})
}
render() {
return (
<div className="content">
{<Saved data={this.state.data} del={this.deletePost}/>}
</div>
);
}
}
export default App;

Cannot Read image of undefined in React app

I'm use the filter method to pick-out one featured item in an array and use that to render it's state in my Home Component. I'm using the filter method in the MainComponent, passing that to the Home Component, where I want the AddCard functional component to render. I'm getting the error message of "cannot read image of undefined" so I'm assuming I'm doing something wrong in passing my props.
MainComponent.js
class Main extends Component{
constructor(props){
super(props);
this.state={
whyfastpack: WHYFASTPACK
};
}
render(){
const LandingPage =()=>{
return (
<Landing />
);
};
const HomePage=()=>{
return (
<Home
lightweight={this.state.whyfastpack.filter(lightweight => lightweight.featured)[0]}
/>
);
};
return(
<div>
<Header />
<Switch>
<Route exact path='/' component={LandingPage} />
<Route path ='/home' component={HomePage} />
HomeComponent.js
...
</div>
<div className='col-md m-1'>
<AddCard />
</div>
</div>
....
function RenderCard({ item }) {
return (
<Card>
<CardImg src={this.image} alt={item.name} />
<CardBody>
<CardTitle>{item.name}</CardTitle>
<CardText>{item.comment}</CardText>
</CardBody>
</Card>
);
}
function AddCard(props) {
return (
<div className="container">
<div className="row">
<div className="col-md m-1">
<RenderCard item={props.lightweight} />
</div>
</div>
</div>
);
}
whyFastPack.js
export const WHYFASTPACK = [
{
id: 0,
image: 'images/pnw.jpg',
name: 'Reduce Weight',
comment: 'Carry only what you need for the day, not a month! With fast-packing you only need to bring enough to get you through each day!',
featured: true,
}
]
You neglected to pass a lightweight prop to AddCard from HomeComponent.
<div className='col-md m-1'>
<AddCard lightweight={this.props.lightweight} />
</div>

Accesing object using props in ReactJs

I'm trying to access object keys using props as an index but it's not working. Error: Objects are not valid as a React child (found: object with keys {id, name, img_url, location}). If you meant to render a collection of children, use an array instead.
I am new to React so I appreciate any help.
My code:
class ExpandCard extends React.Component {
render() {
const props = this.props;
const profiles = props.profiles;
return(
<>
<div className="">
{profiles[props.active]}
</div>
</>
);
}
}
class App extends React.Component {
state = {
profiles: testData,
active: null,
}
getActive = (dataFromCard) => {
console.log('the magic number is', dataFromCard);
this.setState({active: dataFromCard});
}
render() {
return (
<div>
<div className="wrapper">
<header>
<div className="logo">LOGO</div>
</header>
<Form />
<div className="cards">
<div className="card-list">
{this.state.profiles.map(profile => <Card key={profile.id} {...profile} activeCard={this.getActive} />)}
</div>
<div className="expand-card">
<ExpandCard active={this.state.active} profiles={this.state.profiles} />
</div>
</div>
</div>
</div>
);
}
}
It looks like {profiles[props.active]} returns an object that looks like this:
{ id, name, img_url, location }
You can't return an object from a React component, maybe you meant to return {profiles[props.active].name}?

TypeError: books.map is not a function

I'm creating a react app.
I have 2 files
AuthorQuiz.js
index.js
And I have 2 components
AuthorQuiz
Turn
Turn component is embedded in the AuthorQuiz component and the AuthorQuiz is the main component.
And data is coming from index.js as a spread operator
AuthorQuiz.js
function AuthorQuiz({ turnData }) {
return (
<div className="container-fluid">
<Turn {...turnData} />
</div>
);
}
function Turn(author, books) {
return (
<div className="row turn" style={{ backgroundColor: 'white' }}>
<div className="col-4 offset-1">
<img src={author.imageUrl} className="authorImage" alt="Author" />
</div>
<div className="col-6">
{books.map(title => (
<p>{title}</p>
))}
</div>
</div>
);
}
index.js
const authors = [
{
name: 'Mark Twain',
imageUrl: 'images/authors/marktwain.jpg',
imageSource: 'Wikimedia Commons',
books: ['The Adventures of Hucklebery Finn']
}
];
const state = {
turnData: {
author: authors[0],
books: authors[0].books
}
};
ReactDOM.render(<AuthorQuiz {...state} />, document.getElementById('root'));
but when I run my code I get an error
TypeError: books.map is not a function
You haven't destructured the props in Turn component, which leads to it being treated incorrectly by the component
function Turn({ author, books }) { // Destructure props here
return (
<div className="row turn" style={{ backgroundColor: 'white' }}>
<div className="col-4 offset-1">
<img src={author.imageUrl} className="authorImage" alt="Author" />
</div>
<div className="col-6">
{books.map(title => (
<p>{title}</p>
))}
</div>
</div>
);
}

Components in React

I have the following code from the React documentation. Question:
Why do i have to use the formatDate function? Lets say i just want to use the raw date output from the new Date () function, why cant i just use it as props.date? does not seem to work.
function formatDate(date) {
return date.toLocaleDateString();
}
function Avatar(props) {
return (
<img className="Avatar"
src={props.user.avatarUrl}
alt={props.user.name} />
);
}
function UserInfo(props) {
return (
<div className="UserInfo">
<Avatar user={props.user} />
<div className="UserInfo-name">
{props.user.name}
</div>
</div>
);
}
function Comment(props) {
return (
<div className="Comment">
<UserInfo user={props.author} />
<div className="Comment-text">
{props.text}
</div>
<div className="Comment-date">
{formatDate(props.date)}
</div>
</div>
);
}
const comment = {
date: new Date(),
text: 'I hope you enjoy learning React!',
author: {
name: 'Hello Kitty',
avatarUrl: 'http://placekitten.com/g/64/64'
}
};
ReactDOM.render(
<Comment
date={comment.date}
text={comment.text}
author={comment.author} />,
document.getElementById('root')
);

Resources