Iterating through a Wordpress Object REACT js - reactjs

i am new to REACT.js and your advise would be much appreciated
i have a list of categories i have placed a post under
how do i display these list of categories in react js?
i tried the below:
<ul>
{post.categories.map((category) => {
return(
<li>{category.name}</li>
);
})};
</ul>
but i get the error:
TypeError: post.categories.map is not a function
BELOW ARE MY FILES
app/scr/components/Blog/Index.js
import React, { Component } from 'react';
import Layout from '../../components/Layout/Layout';
import { Link } from 'react-router-dom';
class Index extends Component {
render() {
return(
<Layout>
<ul>
{this.props.posts.map((post) => {
if (post) {
return(
<li key={post.ID} className="card">
<div>{post.title}</div>
<div>{post.date}</div>
<ul>
{post.categories.map((category) => {
return(
<li>{category.name}</li>
);
})};
</ul>
</li>
);
} else {
return null;
}
})}
</ul>
</Layout>
);
}
}
export default Index;
app/scr/containers/BlogBuilder/BlogIndexBuilder.js
import React, { Component } from 'react';
import BlogIndex from '../../components/Blog/Index';
import axios from 'axios';
class BlogIndexBuilder extends Component {
state = {
posts: []
};
componentDidMount() {
axios
.get(
"http://public-api.wordpress.com/rest/v1/sites/emma.wordpress.com/posts"
)
.then(res => {
this.setState({ posts: res.data.posts });
console.log(this.state.posts);
})
.catch(error => console.log(error));
}
parseOutScripts(content) {}
render() {
return (
<div>
<BlogIndex
posts={this.state.posts}
/>
</div>
);
}
}
export default BlogIndexBuilder;
app/scr/components/Layout/Layout.js
import React from 'react';
import Aux from '../../hoc/Aux';
const layout = (props) => {
return(
<Aux>
<main>{props.children}</main>
</Aux>
)
};
export default layout;

You can't map over an object. It needs to be an array. You can transform it to an array if you want by using Object.values(post.categories):
<ul>
{Object.values(post.categories).map((category) => {
return(
<li>{category.name}</li>
);
})};
</ul>

Related

react : why is axios api call not using proxy in package.json?

I have a react app that i've made and it is working great in storybook with a mock for data retrieving.
When I switch to yarn start to check the app without mock, the page is loading some components but not the main component (PostPageCardContainer) which is only displaying "loading" (see the code below).
The component which load properly make api calls like this in ComponentDidMount :
axios.get("/api/blog/categories/").then((res) => {
const categories = res.data.results;
this.setState({
categories,
loading: false });
and
axios.get("/api/blog/tags/").then((res) => {
const tags = res.data.results;
this.setState({
tags,
loading: false });
}); }
The components that dont load make an api call like this in COmponentDidMount:
PostPageCard.js:
const pk = this.props.match.params.id;
axios.get(`/api/cms/pages/${pk}/`).then((res) => {
const post = res.data;
this.setState({
post,
loading: false });
}) }
PostDetail.js
axios.get(`/api/cms/pages/${this.props.postPk}/`).then((res) => {
this.setState({
data: res.data,
loading: false
}); });
In the browser console, when i try to load the page i get :
printWarnings # webpackHotDevClient.js:138
:3000/api/cms/pages/6/:1
Failed to load resource: the server responded with a status of 404 (Not Found)
And when i hover the mouse on the link i get http://localhost:3000/api/cms/pages/6.
In fact the react page is being served on localhost:3000 but I have put "proxy": "http://172.20.128.2:8000" in packages.json so my api call go on this adress.
How come some api calls go on the good adress and others dont?
The issue is similar to this : How to set proxy when using axios to send requests? and this Axios not using proxy setting with https and this axios request ignores my proxy and even when hardcoded I can't fetch any data but there is not really a solution except using fetch or restarting the machine
I ve tried to hardcode the proxy in the api call like axios.get(http://172.20.128.2:8000/api/cms/pages/${this.props.postPk}` and removed the proxy line from package.json but then nothing is loading properly...
Here is some sample of the code:
index.js
import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter } from "react-router-dom";
import App from "./components/App";
import 'bootstrap/dist/css/bootstrap.css';
import { MemoryRouter } from "react-router-dom";
ReactDOM.render(
<React.StrictMode>
<MemoryRouter initialEntries={["/"]}>
<App/>
</MemoryRouter>
</React.StrictMode>,
document.getElementById("root")
);
App.js
import React from "react";
import { Route, Switch } from "react-router";
import { Container, Row } from "react-bootstrap";
import { BlogPage } from "./BlogPage";
import { PostPage } from "./PostPage";
function App() { return (
<Switch>
<Route path="/post/:id([\d]+)" component={PostPage}/>
<Route path="/tag/:tag/:page([\d]+)?" component={BlogPage}/>
<Route path="/:page([\d]+)?" component={BlogPage}/>
<Route
path="*"
component={() => (
<Container> <Row>
<h1>404</h1> </Row>
</Container> )}
/> </Switch>
); }
export default App;
BlogPage.js
import React from "react";
import { Container, Row } from "react-bootstrap";
import { TopNav } from "./TopNav";
import { Footer } from "./Footer";
import { PostPageCardContainer } from "./PostPageCardContainer";
import { SideBar } from "./SideBar";
class BlogPage extends React.Component { render() {
return (
<div>
<TopNav />
<Container>
<Row>
<PostPageCardContainer {...this.props} />
<SideBar />
</Row>
</Container>
<Footer />
</div> );
} }
export { BlogPage };
Postpagecardcontainer.js
import React from "react";
import axios from "axios";
import { Col } from "react-bootstrap";
import { Link } from "react-router-dom";
import { generatePath } from "react-router";
import _ from 'lodash';
import { PostPageCard } from "./PostPageCard";
class PostPageCardContainer extends React.Component {
constructor(props) {
super(props); this.state = {
posts: [],
pageCount: 0,
pageStep: 2,
};
this.getPosts = this.getPosts.bind(this);
}
componentDidMount() {
this.getPosts();
}
componentDidUpdate(prevProps) {
if (prevProps.location !== this.props.location) {
this.getPosts(); }
}
getCurPage() {
// return the page number from the url
const page = this.props.match.params.page;
return page === undefined ? 1 : parseInt(page);
}
getPrePageUrl() {
const target = _.clone(this.props.match.params);
target.page = this.getCurPage() - 1;
return generatePath(this.props.match.path, target);
}
getNextPageUrl() {
const target = _.clone(this.props.match.params);
target.page = this.getCurPage() + 1;
return generatePath(this.props.match.path, target);
}
getPosts() {
let category = this.props.match.params.category === undefined ? "*" : this.props.match.params.category;
let tag = this.props.match.params.tag === undefined ? "*" : this.props.match.params.tag;
let offset = (this.getCurPage() - 1) * this.state.pageStep;
const url = `/api/blog/posts/?limit=${this.state.pageStep}&offset=${offset}&category=${category}&tag=${tag}`;
axios.get( url).then((res) => {
const posts = res.data.results;
this.setState({
posts,
pageCount: Math.ceil(parseInt(res.data.count) / this.state.pageStep),
});
});
}
render() {
return (
<Col md={8}> {this.state.posts.map((post) => (
<PostPageCard postPk={post.id} key={post.id} /> ))}
<nav aria-label="Page navigation example">
<ul className="pagination">
<li className={
this.getCurPage() <= 1 ? "page-item disabled" : "page-item" }>
<Link to={this.getPrePageUrl()}
className="page-link" >
Previous
</Link>
</li>
<li className={this.getCurPage() >= this.state.pageCount ? "page-item disabled" : "page-item" }>
<Link to={this.getNextPageUrl()}
className="page-link" >
Next
</Link>
</li>
</ul>
</nav>
</Col>
);
}
}
export { PostPageCardContainer };
PostPage.js
import React from "react";
import { Container, Row } from "react-bootstrap";
import { TopNav } from "./TopNav";
import { Footer } from "./Footer";
import { SideBar } from "./SideBar";
import { PostDetail } from "./PostDetail";
class PostPage extends React.Component { render() {
return ( <div>
<TopNav/> <Container>
<Row>
<PostDetail {...this.props} /> <SideBar/>
</Row> </Container> <Footer/>
</div> );
} }
export { PostPage };
PostDetail.js
import React from "react";
import axios from "axios";
import { StreamField } from "./StreamField/StreamField";
class PostDetail extends React.Component {
constructor(props) {
super(props); this.state = {
post: [],
loading: true, };
}
componentDidMount() {
const pk = this.props.match.params.id;
axios.get(`/api/cms/pages/${pk}/`).then((res) => {
const post = res.data;
this.setState({
post,
loading: false });
}) }
render() {
if (!this.state.loading) {
const post = this.state.post;
return (
<div className="col-md-8">
<img src={post.header_image_url.url} className="img-fluid rounded" alt=""/>
<hr />
<h1>{post.title}</h1>
<hr />
<StreamField value={post.body} />
</div> );
}
else {
return <div className="col-md-8">Loading...</div>;
}
}
}
export { PostDetail };
PostPageCard.js
import React from "react";
import { Link } from "react-router-dom";
import axios from "axios";
class PostPageCard extends React.Component {
constructor(props) {
super(props); this.state = {
data: null,
loading: true,
};
}
componentDidMount() {
axios.get(`/api/cms/pages/${this.props.postPk}/`).then((res) => {
this.setState({
data: res.data,
loading: false
}); });
}
renderPost(data) {
const dateStr = new Date(data.pub_date).toLocaleString();
return (
<div className="card mb-4">
<Link to={`/post/${data.id}`}> <img src={data.header_image_url.url} className="card-img-top" alt=""/> </Link>
<div className="card-body">
<h2 className="card-title">
<Link to={`/post/${data.id}`}>{data.title}</Link>
</h2>
<p className="card-text">{data.excerpt}</p>
<Link to={`/post/${data.id}`} className="btn btn-primary">Read More → </Link>
</div>
<div className="card-footer text-muted">Posted on {dateStr}
</div>
</div>
); }
render() {
if (this.state.loading) {
return 'Loading...'; }
else{
return this.renderPost(this.state.data); }
} }
export { PostPageCard };

How to add button cart in shopping cart react redux?

how to add an action when the add button is clicked then the item will display the product?
This code does not display the product when clicked
I've been fiddling with it but it's still an error, who knows, someone here can help me and fix the code and explain it
cartAction.js
import {ADD_TO_CART} from './ActionType';
export const addToCart = (items) =>{
return{
type: ADD_TO_CART,
items //I'm confused about what to do in the action payload here
}
}
cartReducer.js
import ImgT from './images/image-product-1-thumbnail.jpg';
import {ADD_TO_CART} from './ActionType';
const initState = {
items: [
{id:1,title:'title',
brand:cc',
images:ImgT,
desc:'helo world',
price:125.00}
],addItems:[],
total:0
}
const cartReducer= (state = initState,action)=>{
if(action.type === ADD_TO_CART){
return {...state, addItems:state.addItems} //I'm confused about what to do in the action payload here
}
return state
}
export default cartReducer;
cart.js
import React, { Component } from 'react';
import { connect } from 'react-redux';
class Cart extends Component {
render() {
return (
<div>
{this.props.Items.map(item =>{
<div key={item.id}>
{/* <img src={item.images} /> */}
<p>{item.title}</p>
<h4>brand: {item.brand}</h4>
<p>{item.price}</p>
</div>
})
}
</div>
);
}
}
const mapToProps = (state ) =>{
return{
Items:state.addItems}
}
export default connect(mapToProps)(Cart);
Home.js
import React, { Component } from 'react';
import { connect } from 'react-redux';
import Cart from './Cart';
import {addToCart} from './cartAction';
class Home extends Component{
handleClick = () =>{
this.props.addToCart()
}
render(){
let item = this.props.items.map(item =>{
return(
<div className='card' key={item}>
<img style={{width:'10rem'}} src={item.images}/>
<p className='card-title '>{item.title}</p>
<h2 className='card-title fs-4'>{item.brand}</h2>
<button onClick={() => this.handleClick()} className='btn btn-primary'>Add to cart</button>
<h3 className='fs-5'>{item.price}</h3>
</div>
)
})
return(
<div className="container">
<h3>Home</h3>
{item}
<Cart/>
</div>
)
}
}
const mapToProps = (state) => {
return{
items:state.items,
}
}
const mapDispatchToProps = (dispatch) => {
return{
addToCart: () => dispatch(addToCart())}
}
export default connect(mapToProps,mapDispatchToProps)(Home);

Context Provider is not working in React.js

I am a beginner in React js and I'm trying to implement Context Provider in React js. But while I'm not getting the perfect output.
I am storing contact info in context.js which will act as Context Provider and in App.js I imported it in App.js then in Contacts.js I Consumed the Consumer and got the value but still, I'm getting the blank page and I'm not sure why I cannot bind the contact component in Context provider
Context.js
import React, {Component} from 'react';
const Context = React.createContext();
export class Provider extends Component {
state = {
contacts: [{
id: 1,
name: "dasd B",
email: "asdas#gmail.com",
phone: "dsadas"
}
};
render() {
debugger
return (
<Context.Provider value={this.state}>
{this.props.childern}
</Context.Provider>
);
}
}
export const Consumer = Context.Consumer;
App.js
import React, { Component } from 'react';
import Header from './components/Header';
import Contacts from './components/Contacts'
import 'bootstrap/dist/css/bootstrap.min.css';
import { Provider } from './Context'
class App extends Component {
render() {
return (
<Provider>
<div className="App">
<div className="container">
<Contacts />
</div>
</div>
</Provider>
);
}
}
export default App;
Contacts.js
import React, { Component } from 'react'
import Contact from './Contact';
import { Consumer } from '../Context';
class Contacts extends Component {
deleteContact = id => {
const { contacts } = this.state;
const newContacts = contacts.filter(contact => contact.id!== id);
this.setState({
contacts: newContacts
});
};
render() {
debugger
return(
<Consumer>
{value => {
const { contacts } = value;
return (
<React.Fragment >
{contacts.map(contact => (
<Contact
key = {contact.id}
contact={contact}
deleteClickHandler = {this.deleteContact.bind(this, contact.id)}>
</Contact>
))}
</React.Fragment>
);
}}
</Consumer>
);
}
}
export default Contacts;
Contact.js
import React, { Component } from 'react'
import PropTypes from 'prop-types'
class Contact extends Component {
state = {
showContactinfo : false
};
onDeleteClick = () => {
this.props.deleteClickHandler();
}
onEditClick() {
}
render() {
const { name, email, phone } =this.props.contact;
const { showContactinfo } = this.state;
return (
<div className="card card-body mb-3">
<h4>{name}
{showContactinfo ? (
<div className="float-right">
<i
onClick= {this.onEditClick}
style={{cursor: 'pointer', fontSize: 'medium'}}
className="fas fa-edit mr-3"></i>
<i
onClick= {this.onDeleteClick}
style={{cursor: 'pointer', fontSize: 'medium'}}
className="fa fa-trash-alt"></i>
</div>):
<i className="fa fa-sort-down float-right"
style={{cursor: 'pointer'}}
onClick={() =>
this.setState({ showContactinfo: !this.state.showContactinfo})}></i>}
</h4>
{showContactinfo ? (
<ul className="list-group">
<li className="list-group-item">Email: {email}</li>
<li className="list-group-item">Phone: {phone}</li>
</ul>) : null}
</div>
)
}
}
Contact.propTypes = {
contact: PropTypes.object.isRequired,
deleteClickHandler: PropTypes.func.isRequired
}
export default Contact;

Why am I getting a blank screen while following React JS?

I am following the current tutorial:
Youtube tutorial at 12:51 mins.
I expect to see bunch of posts on my screen but my screen remains blank.
It appears I have followed everything told in the tutorial.
import React, { Component } from 'react';
class Posts extends Component {
constructor(props) {
super(props);
this.state = {
posts: []
}
}
componentWillMount() {
fetch('https://jsonplaceholder.typicode.posts')
.then(res => res.json())
.then(data => this.setState({posts: data}))
}
render() {
const postItems = this.state.posts.map(post => (
<div key={post.id}>
<h3>{post.title}</h3>
<p>{post.body}</p>
</div>
));
return (
<div>
<h1>Posts</h1>
{ postItems }
</div>
);
}
}
export default Posts;
and
import React, { Component } from 'react';
import './App.css';
import Posts from './components/Posts'
class App extends Component {
render() {
return (
<div className="App">
<Posts />
</div>
);
}
}
export default App;
My browser screen remains blank and I do not see any errors on console.
What am I missing ?
Don't know about the tutorial but it looks outdated...
Here is your App.js (parent component):
import React, { Component } from 'react';
import Posts from './Posts';
export default class App extends Component {
state = { posts: [] };
//fetch the posts and store them in the state
componentDidMount() {
fetch('https://jsonplaceholder.typicode.com/posts')
.then(response => response.json())
.then(posts => this.setState({ posts }))
.catch(error => console.log(error));
}
render() {
return (
<div>
{/* pass the state (posts) as props to Posts */}
<Posts posts={this.state.posts} />
</div>
);
}
}
Here is your Posts.js:
import React from 'react';
// No need for a class based comp
// destructure the props and you have all your data
const Posts = ({ posts }) => (
<div>
{posts.map(post => (
<div key={post.id}>
<h3>{post.title}</h3>
<p>{post.body}</p>
<hr />
</div>
))}
</div>
);
export default Posts;
Live Demo: https://jsfiddle.net/ctszdue9/7/
Try putting side effect/ api call inside
componentDidMount() { }
Change URL
https://jsonplaceholder.typicode.posts/
TO
https://jsonplaceholder.typicode.com/posts

ReactJS error TypeError: Cannot read property 'map' of undefined

I'm attempting to consume a JSON API using fetch; the error mentioned above appears on the following line: **this.state.data.map( (dynamicData,key)=>**
This is my ReactJS code with the error line in bold:
import React, { Component } from 'react';
import './App.css';
class App extends Component {
//constructor
constructor() {
super();
this.state = {
data: [],
}
} //end constructor
componentDidMount(){
return fetch('https://jsonplaceholder.typicode.com/todos')
.then((response)=>response.json())
.then((responseJson)=>
{
this.setState({
data:responseJson.todos
})
console.log(this.state.data)
})
} // end component did mount
render() {
return (
<div>
<h2>Todo:</h2>
<div>
{
**this.state.data.map( (dynamicData,key)=>**
<div>
<span> {dynamicData.userId} </span>
<span> {dynamicData.id} </span>
</div>
)
}
</div>
</div>
);
}
}
export default App;
Could I get some help as to what I'm doing wrong? Thanks in advance
import React, { Component } from "react";
import { render } from "react-dom";
class App extends Component {
state = {
data:[],
url: "https://jsonplaceholder.typicode.com/todos"
};
componentDidMount() {
fetch(this.state.url)
.then(response => response.json())
.then(data => this.setState({ data }));
}
render() {
const { data } = this.state;
data && console.log(data);
return (
<div>
{data &&
data.map(item => <div> Hello User With Id: {item.userId} </div>)}
</div>
);
}
}
render(<App />, document.getElementById("root"));
Your didMount should look like mine also, setState takes a callback so if you wanted to see what the data looked like it would be like this
this.setState({ data }, () => console.log(this.state.data))
In your render it looks like you forgot the parenthesis after the arrow function in map.
render() {
return (
<div>
<h2>Todo:</h2>
<div>
{
this.state.data.map((dynamicData,key)=> (
<div>
<span> {dynamicData.userId} </span>
<span> {dynamicData.id} </span>
</div>
))
}
</div>
</div>
);
}

Resources