How can I render this object in React? - javascript

My JSON:
{
"id": 1,
"userId": 34,
"cerealId": 1,
"metadata": {
"latitude": "47.484574",
"longitude": "4.341844",
"precision": "461.43"
},
"createdAt": "2020-07-13T00:00:00.000Z",
"updatedAt": "2020-07-13T00:00:00.000Z"
}
I need to render the object "metadata" and this is my code:
import React,{useState,useEffect, Fragment} from 'react';
import {getCookie} from '../helpers/Helpers';
import moment from 'moment';
import { read } from './apiAdmin';
const IndividualSample = (props) => {
const token = getCookie('accessToken') //// <-- right one
//const Id = getCookie('token')
const [order, setOrder] = useState({});
const [error, setError] = useState(false);
const loadSingleOrder = orderId => {
read(orderId,token).then( data => {
if (data.error){
setError(data.error)
} else {
setOrder(data)
}
})
}
const showInput = (key, value) => {
return (
<div className="input-group mb-2 mr-sm-2">
<div className="input-group-prepend">
<div className="input-group-text">{key}</div>
</div>
<input type="text" value={value} className="form-control" readOnly/>
</div>
)
}
useEffect (() => {
const orderId = props.match.params.orderId
loadSingleOrder(orderId)
},[props])
const showSingleSample = () => {
return (
<div className="card mr-2 mt-2 mb-5">
<ul className="list-group">
<li className='list-group-item'>ID Sample: {order.id} </li>
<li className="list-group-item">User ID: {order.userId}</li>
<li className="list-group-item">Cereal ID: {order.cerealId}</li>
<li className='list-group-item' style={{fontWeight:'bold'}}>Created At:{" "}
{moment(order.createdAt).locale('es').format('LL')}
</li>
<h2 className='mt-2 mb-5 text-center' >METADATA :</h2>
{order.data?.map((p, pIndex) => (
<div className='mb-4' key={pIndex} style={{padding:'20px', border:'1px solid indigo'}}>
I need render this ---> {showInput('Latitude:', p.latitude)}
{showInput('Longitude:', p.longitude)}
</div> ))}
</ul>
</div>
)
}
return(
<>
<h1>Soy Individual samples</h1>
<div className='container'>
{showSingleSample()}
{JSON.stringify(order.metadata)}
</div>
</>
)
}
I can render the other params cerealId, userId etc. But as I didn't receive the object as an array I don't know how render it in the right way.
I can only see the params in JSON.stringify(order.metadata),but I need to render them inside a div tag.
I can't render the 'metadata'. If someone can help me I will appreciate it!

metadata is an object, you will have to use Object.entries (polyfill may be needed):
{ Object.entries(order.metadata).map(([key, value]) => (
<div>{key}: {value}</div>
))}
Also, make sure it's order.metadata or order.data.

Related

React - Cards are not rendering as I am calling for the data in this API

I am receiving a response from the API, but the data doesn't display on the card. I don't think it has much to do with the data I think it has much to do with the card appearing itself first. Here is how the search file is set up, pretty straight forward. As you see I did set up a container to hold the card as I map through it.
import '../styles/searchPage.css'
import SearchCard from '../components/SearchCard';
const API_URL = 'https://api.openbrewerydb.org/breweries?by_city';
const brewery1 = {
"id": "10-barrel-brewing-co-san-diego",
"name": "Nirmanz Food Boutique",
"brewery_type": "large",
"street": "1501 E St",
"phone": "7739888990 ",
"address": null,
"city": "San Diego",
"state": "California",
"postal_code": "92101-6618",
"country": "United States",
}
function SearchPage() {
const [cards, setCards] = useState([]);
const [searchTerm, setSearchTerm] = useState('');
const searchRestaurants = async (name) => {
const req = await fetch(`${API_URL}&s=${name}`);
const data = await req.json()
console.log(data[0].name)
setCards({data: data.name})
}
useEffect(() => {
searchRestaurants('')
}, [])
return (
<div className='search'>
<h1>Enter a City or Town name</h1>
<div className='search-container'>
<input
type="text"
name="search"
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
onKeyPress={(e) => {
if (e.key === 'Enter'){
setCards(searchTerm);
}
}}
placeholder="Search..."
class="search-input"
/>
<button
className='next'
onClick={()=> searchRestaurants(searchTerm)}
>Go</button>
</div>
{
cards?.length > 0
? (
<div className="container">
{cards.map((card) =>(
<SearchCard brewery1={brewery1}/>
))}
</div>
) :
(
<div className="empty">
<h2>Found 0 Breweries</h2>
</div>
)
}
</div>
);
}
export default SearchPage
Here is the my JSX for my search card labeling out what I want to display inside that card.
import '../styles/searchPage.css'
const SearchCard = ({brewery1}) => {
return (
<div className="card">
{/* <img src={brewery1.Poster !== 'N/A' ? brewery1.Poster : 'https://via.placeholder.com/400'} alt={brewery1.name /> */}
<div>
<span>{brewery1.id}</span>
<h3>{brewery1.brewery_type}</h3>
<h2>{brewery1.street}</h2>
<h2>{brewery1.adress}</h2>
<h2>{brewery1.phone}</h2>
<h2>{brewery1.city}</h2>
<h2>{brewery1.state}</h2>
<h2>{brewery1.postal_code}</h2>
<h2>{brewery1.country}</h2>
</div>
</div>
)
}
export default SearchCard;
Change this:
setCards(data);
And this:
<SearchCard brewery1={card}/>
In your searchRestaurant method set the data like this:
const searchRestaurants = async (name) => {
const req = await fetch(`${API_URL}&s=${name}`);
const data = await req.json()
//make sure that data got your restaurants list
setCards(data)
}
and in the render like this:
cards.map(card => <SearchCard brewery1={card}/>)

How to map through data coming from smart contract

So I'm reading data from a smart contract and trying to map through it to display on a frontend but it keeps returning an error
data is undefined
I'll post my code below, I'm really looking forward to some help
import React , { useState , useEffect , Fragment } from 'react';
import {Link} from 'react-router-dom';
import { Tab, Tabs, TabList, TabPanel } from 'react-tabs';
import 'react-tabs/style/react-tabs.css';
import CardModal from '../CardModal';
import MarketplaceJSON from "../../../Marketplace.json";
import axios from "axios";
const TodayPicks = () => {
const [dataTab] = useState(
[
{
id: 1,
title: "All",
},
]
)
const [visible , setVisible] = useState(8);
const showMoreItems = () => {
setVisible((prevValue) => prevValue + 4);
}
const [modalShow, setModalShow] = useState(false);
const [data, updateData] = useState();
const [dataFetched, updateFetched] = useState(false);
async function getAllNFTs() {
const ethers = require("ethers");
//After adding your Hardhat network to your metamask, this code will get providers and signers
const provider = new ethers.providers.Web3Provider(window.ethereum);
const signer = provider.getSigner();
//Pull the deployed contract instance
let contract = new ethers.Contract(MarketplaceJSON.address, MarketplaceJSON.abi, signer)
//create an NFT Token
let transaction = await contract.getAllNFTs()
//Fetch all the details of every NFT from the contract and display
const items = await Promise.all(transaction.map(async i => {
const tokenURI = await contract.tokenURI(i.tokenId);
let meta = await axios.get(tokenURI);
meta = meta.data;
let price = ethers.utils.formatUnits(i.price.toString(), 'ether');
let item = {
price,
tokenId: i.tokenId.toNumber(),
seller: i.seller,
owner: i.owner,
image: meta.image,
name: meta.name,
description: meta.description,
}
return item;
}))
updateFetched(true);
updateData(items);
}
if(!dataFetched)
getAllNFTs();
console.log(data);
return (
<Fragment>
<div className="tf-section sc-explore-2">
<div className="themesflat-container">
<div className="row">
<div className="col-md-12">
<div className="seclect-box style3">
<div id="artworks" className="dropdown">
<Link to="#" className="btn-selector nolink">All Artworks</Link>
<ul>
<li><span>Abstraction</span></li>
<li className="active"><span>Skecthify</span></li>
<li><span>Patternlicious</span></li>
<li><span>Virtuland</span></li>
<li><span>Papercut</span></li>
</ul>
</div>
<div id="sort-by" className="dropdown style-2">
<Link to="#" className="btn-selector nolink">Sort by</Link>
<ul>
<li><span>Top rate</span></li>
<li className="active"><span>Mid rate</span></li>
<li><span>Low rate</span></li>
</ul>
</div>
</div>
<div className="flat-tabs explore-tab">
<Tabs >
<TabList>
{
dataTab.map(data=> (
<Tab key={data.id} >{data.title}</Tab>
))
}
</TabList>
{
data.map(data =>(
<TabPanel key={data.tokenId}>
{
<div key={data.tokenId} className={`sc-card-product explode style2 mg-bt ${item.feature ? 'comingsoon' : '' } `}>
<div className="card-media">data
<Link to="/item-details-01"><img src={item.img} alt="Axies" /></Link>
<div className="button-place-bid">
<button onClick={() => setModalShow(true)} className="sc-button style-place-bid style bag fl-button pri-3"><span>Place Bid</span></button>
</div>
<Link to="/login" className="wishlist-button heart"><span className="number-like">{item.wishlist}</span></Link>
<div className="coming-soon">{data.feature}</div>
</div>
<div className="card-title">
<h5><Link to="/item-details-01">"{data.title}"</Link></h5>
</div>
<div className="meta-info">
<div className="author">
<div className="avatar">
<img src={data.imgAuthor} alt="Axies" />
</div>
<div className="info">
<span>Creator</span>
<h6> <Link to="/authors-02">{data.nameAuthor}</Link> </h6>
</div>
</div>
<div className="tags">{data.tags}</div>
</div>
<div className="card-bottom style-explode">
<div className="price">
<span>Current Bid</span>
<div className="price-details">
<h5>{data.price}</h5>
<span>= {data.priceChange}</span>
</div>
</div>
<Link to="/activity-01" className="view-history reload">View History</Link>
</div>
</div>
}
{
visible < data.length &&
<div className="col-md-12 wrap-inner load-more text-center">
<Link to="#" id="load-more" className="sc-button loadmore fl-button pri-3" onClick={showMoreItems}><span>Load More</span></Link>
</div>
}
</TabPanel>
))
}
</Tabs>
</div>
</div>
</div>
</div>
</div>
<CardModal
show={modalShow}
onHide={() => setModalShow(false)}
/>
</Fragment>
);
}
export default TodayPicks;
I was also thinking about creating a custom NFT card component to map through but does that work? Please help
You are using Array.map in data and you are not initialising it with [], so on initial load it shows data is undefined error . So Initialise data with [] in useState..
const [data, updateData] = useState([])

axios doesnt fetch on refresh, only on first render

So I've been struggling for a while with retrieving data from APIs and or retrieving local json files. I am using React axios but even with the normal fetch method I am having the same issues. When I fetch the endpoint and save the code, my jsx refreshes and the data appears on the screen but then when I refresh the page, it's no longer there and doesn't appear when I refresh again and again. I have no idea what I am doing wrong. I tried to retrieve the data on the parent and set it as props but still the same problem.
My child component:
import React, { useEffect, useState } from 'react';
import './Card.scss';
import axios from 'axios';
import { ellipsisIcon } from '../../constants/images';
import dataJson from './data.json';
const Card = ({ name, color, icon, currentTime }) => {
const [data, setData] = useState([]);
const [daily, setDaily] = useState([]);
const [weekly, setWeekly] = useState([]);
const [monthly, setMonthly] = useState([]);
useEffect(() => {
const fetchData = async () => {
const result = await axios.get('data.json');
setData(result.data);
setData(
data.filter((item) => {
return item.title === name;
}),
);
setDaily(data[0].timeframes.daily);
setWeekly(data[0].timeframes.weekly);
setMonthly(data[0].timeframes.monthly);
};
fetchData();
}, []);
return (
<div className="card" style={{ backgroundColor: `${color}` }}>
<img src={icon} alt={`${name} icon`} />
<div className="card__container bg-blue">
<div className="card__top-container flex">
<p className="text-white ">{name}</p>
<div className="card__top__elipse-container">
<img src={ellipsisIcon} alt="ellipsis" />
</div>
</div>
<div className="card__bottom-container">
{currentTime === 0 && (
<>
<h1 className="fs-900 text-white">{daily.current}hrs</h1>
<div className="card__bottom__prev-container">
<p className="text-accent ">
Yesterday -<span>{daily.previous}hrs</span>
</p>
</div>
</>
)}
{currentTime === 1 && (
<>
<h1 className="fs-900 text-white">{weekly.current}hrs</h1>
<div className="card__bottom__prev-container">
<p className="text-accent ">
Last Week -<span>{weekly.previous}hrs</span>
</p>
</div>
</>
)}
{currentTime === 2 && (
<>
<h1 className="fs-900 text-white">{monthly.current}hrs</h1>
<div className="card__bottom__prev-container">
<p className="text-accent">
Last Month -<span>{monthly.previous}hrs</span>
</p>
</div>
</>
)}
</div>
</div>
</div>
);
};
export default Card;
My App (Parent):
import { useState, useEffect } from 'react';
import Card from './components/Card/Card';
import {
pbImage,
ellipsisIcon,
exerciseIcon,
playIcon,
careIcon,
socialIcon,
studyIcon,
workIcon,
} from './constants/images';
const cards = [
{
name: 'Exercise',
color: 'hsl(var(--clr-exercise))',
icon: exerciseIcon,
},
{
name: 'Play',
color: 'hsl(var(--clr-play))',
icon: playIcon,
},
{
name: 'Self Care',
color: 'hsl(var(--clr-care))',
icon: careIcon,
},
{
name: 'Social',
color: 'hsl(var(--clr-social))',
icon: socialIcon,
},
{
name: 'Study',
color: 'hsl(var(--clr-study))',
icon: studyIcon,
},
{
name: 'Work',
color: 'hsl(var(--clr-work))',
icon: workIcon,
},
];
function App() {
const [selectedTime, setSelectedTime] = useState(2);
return (
<div className="app bg-dark">
<div className="main__container grid">
<div className="side__card-container">
<div className="side__card__top flex">
<div className="side__card__top__pb-container">
<img
src={pbImage}
alt="pb"
className="side__card__top__pb-image pb-image"
/>
</div>
<div className="side__card__top__person-container">
<p className="fs-600 text-accent">Report for</p>
<h2 className="fs-800 text-white">Jeremy Robson</h2>
</div>
</div>
<div className="side__card__bottom">
<div>Daily</div>
<div>Weekly</div>
<div>Monthly</div>
</div>
</div>
{cards.map((card, _index) => (
<Card
key={_index}
name={card.name}
color={card.color}
icon={card.icon}
currentTime={selectedTime}
/>
))}
</div>
</div>
);
}
export default App;
As I mentioned in the comments, states are updated asynchronously. So, you should be careful when you use a state immediately after setting its value. In your case, you shouldn’t use the data state because you are not sure that it has a value. Try changing to this.
useEffect(() => {
const fetchData = async () => {
const result = await axios.get('data.json');
const filteredData = result.data.filter((item) => {
return item.title === name;
})
setData(filteredData);
// make sure result data isn’t empty
setDaily(result.data[0].timeframes.daily);
setWeekly(result.data[0].timeframes.weekly);
setMonthly(result.data[0].timeframes.monthly);
};
fetchData();
}, []); // "[]" makes the useEffect callback only run after the first render

Why I have got an empty object from my context?

I have a context and try to pass it to my children components:
const PatientContext = createContext([{}]);
function App() {
const [selectedPatient, setSelectedPatient] = useState([]);
const [patients, setPatients] = useState([{ name: 'Taras', age: 19 }, { name: 'Taras', age: 19 }, { name: 'Taras', age: 19 }]);
async function patientsHasChanged() {
const patientService = new PatientService();
const loadedPatients = await patientService.getPatients();
setPatients(loadedPatients);
};
return (
<div className='app'>
<PatientContext.Provider value={[selectedPatient, setSelectedPatient, patients, patientsHasChanged]}>
<Sidebar />
<Content />
</PatientContext.Provider>
</div>
);
}
But if I try use it in my child components I am always getting empty object, how i can fix it?
img with my problem here
UPD:
Here's my component with using context:
const Sidebar = (props) => {
const [patients, selectedPatient, setSelectedPatient] = useContext(PatientContext);
return (
<div className='sidebar'>
<div className='search'>
<input type="text" placeholder='Search' />
<button>New patient</button>
</div>
<div className='list'>
<ul>
{patients.map((p) =>
<li onClick={setSelectedPatient}>
<div className='name'>
{p.name}
</div>
<div className='age'>
{p.age}
</div>
</li>)
}
</ul>
</div>
</div>
);
};
Your problem is you're using an array ([]) for the context; arrays have a given order. You pass in [selectedPatient, setSelectedPatient, patients, patientsHasChanged], and you're unpacking things in a different order ([patients, selectedPatient, setSelectedPatient]), so you get the "wrong" objects.
Instead, use an object ({}) so you can unpack it as you like, and remember to memoize the context value to avoid unnecessary rerenders.
const PatientContext = React.createContext(null);
const Sidebar = (props) => {
const { patients, selectedPatient, setSelectedPatient } = React.useContext(PatientContext);
return (
<div className="sidebar">
<div className="search">
<input type="text" placeholder="Search" />
<a href="/TechTask/new">
<button>New patient</button>
</a>
</div>
<div className="list">
<ul>
{patients.map((p) => (
<li onClick={setSelectedPatient}>
<div className="name">{p.name}</div>
<div className="age">{p.age}</div>
</li>
))}
</ul>
</div>
</div>
);
};
function App() {
const [selectedPatient, setSelectedPatient] = React.useState([]);
const [patients, setPatients] = React.useState([
{ name: "Taras", age: 19 },
{ name: "Taras", age: 19 },
{ name: "Taras", age: 19 },
]);
function patientsHasChanged() {/* elided since SO doesn't support async */}
const patientContext = React.useMemo(() => ({ selectedPatient, setSelectedPatient, patients, patientsHasChanged }), [
selectedPatient,
setSelectedPatient,
patients,
patientsHasChanged,
]);
return (
<div className="app">
<PatientContext.Provider value={patientContext}>
<Sidebar />
</PatientContext.Provider>
</div>
);
}
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.0/umd/react-dom.production.min.js"></script>
<div id="root"></div>

React & Redux: "form submission canceled because the form is not connected"

I am still new in React and Redux. So, I know the existence of redux-form, but Im not intend to use in this project. So, what I am doing is creating a form without using redux-form. This form will grab the data from the reducers and pass it to backend API.
This is my main CreateListing.jsx page.
// #flow
import React from 'react';
import { connect } from 'react-redux';
import { Helmet } from 'react-helmet';
import { SEOService } from '[services]';
import CreateListingFormPage1 from './CreateListing/CreateListingFormPage1';
import CreateListingFormPage2 from './CreateListing/CreateListingFormPage2';
import CreateListingFormPage3 from './CreateListing/CreateListingFormPage3';
import WhereAmI from './CreateListing/WhereAmI';
import SuccessCreateListing from './CreateListing/SuccessCreateListing';
type Props = {
...props...
};
class CreateListing extends React.Component<Props> {
getPageBySequence(pagenum) {
// depending on whether User is logged in or not, show/hide the Login/Signup form which is Page3
let sequence = [ CreateListingFormPage1, CreateListingFormPage2, CreateListingFormPage3 ];
if (this.props.isLoggedIn) {
sequence = [ CreateListingFormPage1, CreateListingFormPage2, CreateListingFormPage2 ];
}
return sequence[pagenum-1];
}
getSubmitCreateListing = (e) => {
e.preventDefault();
const propertyType = this.props.listingType;
const propertyName = this.props.suggestedBuildings.selected;
const propertyBuildingType = this.props.propertyBuildingType;
const bedrooms = this.props.bed;
const bathrooms = this.props.bath;
const price = this.props.price;
const builtUp = this.props.builtUp;
const title = this.props.title;
const tenure = this.props.tenure;
const description = this.props.description;
/* IN CASE USER NOT YET LOGGGED IN */
if(this.props.isLoggedIn === false) {
const email = this.props.email;
const password = this.props.password;
this.props.cacheCreateListing({ email, password, propertyType, propertyName, propertyBuildingType, bedrooms, bathrooms, price, builtUp, title, tenure, description });
}
this.props.cacheCreateListing({ propertyType, propertyName, propertyBuildingType, bedrooms, bathrooms, price, builtUp, title, tenure, description });
if(CreateListingFormPage1.landedTypes.includes(propertyBuildingType)) {
this.props.geocodingRequired(true);
}
else {
this.props.geocodingRequired(false);
}
this.props.onSubmitCreateListing();
}
onAuthenticateAndCreateListingButton() {
if(this.props.isLoggedIn) {
return(
<div role="presentation">
<div className={`column ${this.props.formCurrentPage === 1 ? '':'displayNone'}`}>
<button type="button" className="Button button-next is-red" onClick={this.props.onNextClick}>
NEXT
</button>
</div>
<div className={`column ${this.props.formCurrentPage === 2 || this.props.formCurrentPage === 3 ? '':'displayNone'}`}>
<button type="submit" className="Button button-create is-red" onClick={this.props.onLoadingCreateListing}>
CREATE LISTING
</button>
</div>
</div>
)
}
return <div className={`column ${this.props.formCurrentPage < 3 ? '':'displayNone'}`}>
<button type="button" className="Button button-next is-red" onClick={this.props.onNextClick}>
NEXT
</button>
</div>
}
render() {
if(this.props.isListingCreated){
return <SuccessCreateListing />;
}
else if(this.props.isListingLoading){
return <div className="create-listing-spinner" />
}
const CurrentPage = this.getPageBySequence(this.props.formCurrentPage);
return (
<div className={`CreateListing${this.props.isMobile ? '' : ' is-desktop'}`}>
<Helmet>
<title>{ SEOService.getMetaTitle('Create Property Listing') }</title>
{ SEOService.getCanonicalTag('/blogs') }
</Helmet>
<section className="CreateListing--Main">
<div className="CreateListing--Container">
<div className="CreateListing--WhereAmI">
<WhereAmI page={this.props.formCurrentPage} />
</div>
<div className="CreateListing--Body">
<form className="CreateListing--Form" onSubmit={ this.getSubmitCreateListing }>
<CurrentPage />
<div className='columns'>
<div className='column'/>
{/* CHANGE THIS this.props.formCurrentPage < 3 later */}
<div className={`column ${this.props.formCurrentPage > 1 && this.props.formCurrentPage < 4 ? '':'displayNone'}`}>
<button type="button" className="Button button-back" onClick={this.props.onPrevClick}>
BACK
</button>
</div>
{ this.onAuthenticateAndCreateListingButton() }
<div className='column'/>
</div>
</form>
</div>
</div>
</section>
</div>
);
}
};
const MapStateToProps = (state: State) => ({...});
const MapDispatchToProps = (dispatch: Dispatch) => ({
onLoadingCreateListing: () => dispatch({type: 'CREATE_LISTING_LOADING'}),
onSubmitCreateListing: () => dispatch({type: 'CREATE_LISTING_SUBMIT_FORM'}),})
export default connect(MapStateToProps,MapDispatchToProps)(CreateListing);
So, my <input type="text" /> are all from CreateListingFormPage1, CreateListingFormPage2 and CreateListingFormPage3 and put together in <CurrentPage />. My <form onSubmit={...}></form> is in this CreateListing.jsx page. Im not whether it is allowed to do it like this.
So, when I click submit, I got warning of Form submission canceled because the form is not connected.
My example of <input type="" /> in CreateListingFormPage1 are:
// #flow
import React from 'react';
import { connect } from 'react-redux';
import {Dropdown} from '[elements]';
type Props = {...props...};
class CreateListingFormPage2 extends React.Component<Props> {
static get selectTenure() { return ["Select Tenure"].concat(this.tenureTypes) };
static get selectTitle() { return ["Select Title"].concat(this.titleTypes) };
static get selectBedroom() { return["Select Bedrooms no"].concat(this.bedroomNo) };
static get selectBathroom() { return["Select Bathrooms no"].concat(this.bathroomNo) };
static get tenureTypes(){
return[
"FREEHOLD",
"LEASEHOLD",
"OTHERS"
]};
static get titleTypes(){
return[
"RESIDENTIAL",
"COMMERCIAL",
"INDUSTRIAL"
]};
static get bedroomNo(){
return[
"1",
"2",
"3",
"4",
"5"
]};
static get bathroomNo(){
return[
"1",
"2",
"3",
"4",
"5"
]};
get selectTenure() { return this.constructor.selectTenure; }
get selectTitle() { return this.constructor.selectTitle; }
get selectBedroom() { return this.constructor.selectBedroom; }
get selectBathroom() { return this.constructor.selectBathroom; }
get tenureTypes() { return this.constructor.tenureTypes; }
get titleTypes() { return this.constructor.titleTypes; }
get bedroomNo() { return this.constructor.bedroomNo; }
get bathroomNo() { return this.constructor.bathroomNo; }
hasInputError = (name) => {
if (this.props.errors[name]) {
return ' is-error';
}
return '';
}
render() {
return (
<div className={`Listing--Create${ this.props.isMobile ? '' : ' is-desktop' }`} id='form-second-page'>
{/* <form className="Listing--form"> */}
<div className="Listing--bedrooms-bathrooms">
<div className="type-title">No. of Bedrooms</div>
<Dropdown namespace="bedroom" selected={ this.selectBedroom[0] } options={ this.selectBedroom } onOptionSelect={ this.onBedroomDropdownSelect }/>
<div className="type-title">Asking Price</div>
<input className={`text-input price-input${ this.hasInputError('price')}`} type="text" onChange={ (e) => this.props.onPrice(e.currentTarget.value) } value={this.props.price} placeholder="RM"/>
</div>
<div className="Listing--price-built-up">
<div className="type-title">No. of Bathrooms</div>
<Dropdown namespace="bathroom" selected={ this.selectBathroom[0] } options={ this.selectBathroom } onOptionSelect={ this.onBathroomDropdownSelect }/>
<div className="type-title">Built-up Size</div>
<input className={`text-input built-up-input${ this.hasInputError('built_up_size')}`} type="text" onChange={ (e) => this.props.onBuiltUpSize(e.currentTarget.value) } value={this.props.builtUp} placeholder="sqft."/>
</div>
<div className="Listing--tenure">
<div className="type-tenure">Select Tenure</div>
<Dropdown namespace="tenure" selected={ this.selectTenure[0] } options={ this.selectTenure } onOptionSelect={ this.onTenureDropdownSelect }/>
</div>
<div className="Listing--title">
<div className="type-title">Select Title</div>
<Dropdown namespace="title" selected={ this.selectTitle[0] } options={ this.selectTitle } onOptionSelect={ this.onTitleDropdownSelect }/>
</div>
<div className="Listing--photos">
<div className="type-title">Upload Photos</div>
<button className={`text-input photos-input${ this.hasInputError('photos')}`}>Click to upload</button>
</div>
<div className="Listing--description">
<div className="type-title">Describe your property</div>
<textarea className={`text-input description-input${ this.hasInputError('description')}`} onChange={ (e) => this.props.onDescription(e.currentTarget.value) } value={this.props.description} placeholder="Describe your property"/>
</div>
</div>
);
}
};
const MapStateToProps = (state: State) => ({
...
});
const MapDispatchToProps = (dispatch: Dispatch) => ({
...
})
export default connect(MapStateToProps, MapDispatchToProps)(CreateListingFormPage2);
Basically, there is nothing wrong with my redux store. All the value of the input is captured successfully. The problem is when submitting the form, either the onSubmit or my form structure method is incorrect.
This is CreateListing.js reducer should it be helpful:
const INITIAL_STATE= {
isListingLoading: false,
isListingCreated: false,
}
const CreateListing = (state = INITIAL_STATE, action) => {
switch(action.type){
case 'CREATE_LISTING_LOADING':
return Object.assign({}, state, {isListingLoading: true});
case 'CREATE_LISTING_SUBMIT_FORM':
return Object.assign({}, state, {isListingCreated: true});
default:
return state;
} }
export default CreateListing;
Any help is much appreciated.
if you have any other buttons in your form you should add type="button".
so make changes like this.
<button type="button" className="Button button-create is-red" onClick={this.props.onLoadingCreateListing}>
CREATE LISTING
</button>

Categories