The data returned from backend is as follows.
[
{
id: 1,
address: '991 Folsom St, San Francisco, CA 94107, USA',
info: 'Triplex 4,000 sqft',
cap: '7.1',
position: { lat: 37.778519, lng: -122.405640 }
},
{
id: 2,
address: '1139004, San Francisco, CA 94118, USA',
info: 'Duplex 1,500 sqft',
cap: '6.8',
position: { lat: 37.768519, lng: -122.435640 }
}
]
The reactjs code to normalize data is as follows.
import axios from '../../../util/axios';
import * as schema from '../../../schema';
import { normalize } from 'normalizr';
const normalizePropertyList = response => normalize(response.data.listings_by_id, [schema.propertyList]);
export const getPropertyList = () => axios.get('/api/v1/properties').then(normalizePropertyList);
Schema is defined as follows.
import { normalize, schema } from 'normalizr';
export const propertyList = new schema.Entity('listings_by_id', {}, { idAttribute: 'id' });
The normalized data returned is as follows.
{
"entities": {
"listings_by_id": {
"1": {
"id": 1,
"address": "991 Folsom St, San Francisco, CA 94107, USA",
"info": "Triplex 4,000 sqft",
"cap": "7.1",
"position": {
"lat": 37.778519,
"lng": -122.40564
}
},
"2": {
"id": 2,
"address": "1139004, San Francisco, CA 94118, USA",
"info": "Duplex 1,500 sqft",
"cap": "6.8",
"position": {
"lat": 37.768519,
"lng": -122.43564
}
}
}
},
"result": [
1,
2
]
}
Now in the reducer i need to access this data using selectors. I am a bit confused on how to implement this.
Any help would be appreciated.
Related
My redux reducer function works fine. but is not rendering data fetched from a .json file. I'm using axios to fetch the data from the .json file. Am I right by ftching it like that or is there any other way I can fetch the data?
Here's my products data in json format
{
"products": [
{
"id": 1,
"name": "Airpods Wireless Bluetooth Headphones",
"image": "/images/airpods.jpg",
"description": "Bluetooth technology lets you connect it with compatible devices wirelessly High-quality AAC audio offers immersive listening experience Built-in microphone allows you to take calls while working",
"brand": "Apple",
"category": "Electronics",
"price": 89.99,
"countInStock": 10,
"rating": 4.5,
"numReviews": 12
},
{
"id": 2,
"name": "iPhone 11 Pro 256GB Memory",
"image": "/images/phone.jpg",
"description": "Introducing the iPhone 11 Pro. A transformative triple-camera system that adds tons of capability without complexity. An unprecedented leap in battery life",
"brand": "Apple",
"category": "Electronics",
"price": 599.99,
"countInStock": 7,
"rating": 4.0,
"numReviews": 8
},
{
"id": 3,
"name": "Cannon EOS 80D DSLR Camera",
"image": "/images/camera.jpg",
"description":
"Characterized by versatile imaging specs, the Canon EOS 80D further clarifies itself using a pair of robust focusing systems and an intuitive design",
"brand": "Cannon",
"category": "Electronics",
"price": 929.99,
"countInStock": 10,
"rating": 3,
"numReviews": 12
},
{
"id": 4,
"name": "Sony Playstation 4 Pro White Version",
"image": "/images/playstation.jpg",
"description":
"The ultimate home entertainment center starts with PlayStation. Whether you are into gaming, HD movies, television, music",
"brand": "Sony",
"category": "Electronics",
"price": 399.99,
"countInStock": 11,
"rating": 5,
"numReviews": 12
},
{
"id": 5,
"name": "Logitech G-Series Gaming Mouse",
"image": "/images/mouse.jpg",
"description":
"Get a better handle on your games with this Logitech LIGHTSYNC gaming mouse. The six programmable buttons allow customization for a smooth playing experience",
"brand": "Logitech",
"category": "Electronics",
"price": 49.99,
"countInStock": 7,
"rating": 3.5,
"numReviews": 10
},
{
"id": 6,
"name": "Amazon Echo Dot 3rd Generation",
"image": "/images/alexa.jpg",
"description":
"Meet Echo Dot - Our most popular smart speaker with a fabric design. It is our most compact smart speaker that fits perfectly into small space",
"brand": "Amazon",
"category": "Electronics",
"price": 29.99,
"countInStock": 0,
"rating": 4,
"numReviews": 12
}
]
}
Reducer Function
import * as types from '../types'
const initialState = {
products: [],
error: null,
loading: false
}
export const productListReducer = (state = initialState, action) => {
switch(action.type) {
case types.PRODUCT_LIST_REQUEST:
return {
loading: true,
products: []
}
case types.PRODUCT_LIST_SUCCESS:
return {
loading: false,
products: action.payload
}
case types.PRODUCT_LIST_FAIL:
return {
loading: false,
error: action.payload
}
default:
return state;
}
}
Products Action
import axios from 'axios'
import * as types from '../types'
export const listProducts = () => async (dispatch) => {
try {
dispatch({ type: types.PRODUCT_LIST_REQUEST })
const { data } = await axios.get('/products')
dispatch({
type: types.PRODUCT_LIST_SUCCESS,
payload: data
})
} catch (err) {
dispatch({
type: types.PRODUCT_LIST_FAIL,
payload: err.response && err.response.data.message ? err.response.data.message : err.message
})
}
}
This is my Homescreen component where I render the data from the reducer
import Product from '../components/Product'
import { connect } from 'react-redux'
import { listProducts } from '../redux/actions/productActions'
import Loader from '../components/Loader'
import Message from '../components/Message'
const HomeScreen = ({ productList: { products, error, loading }, listProducts }) => {
useEffect(() => {
listProducts()
// eslint-disable-next-line
}, [])
return (
<Fragment>
<ProductCarousel />
<h1 className='m-4'>Top Trends</h1>
<div style={{ borderBottom: '3px blue solid', width: '10%', alignContent: 'center' }}></div>
{loading ? (<Loader />) : error ? <Message variant='danger'>{error}</Message> : <Row>
{products.map((product) => (
<Col sm={12} md={6} lg={4} xl={3}>
<Product product={product} />
</Col>
))}
</Row>}
Please I"d like to know what I"m doing wrong
this is the screen shot of the error
PS: Im not fetching from an API. just from a json file
Screenshot of the network on chrome
When I am trying the console log the state its saying Undefined.. I also placed the JSON file.
I have posted the endpoint json file here. I believe there is an issue while hooking up json.
When I am trying the console log the state its saying Undefined.. I also placed the JSON file.
I have posted the endpoint json file here. I believe there is an issue while hooking up json.
class App extends Component {
state = {
content: [{ coord: "" }, { base: "" }]
};
componentDidMount() {
axios
.get(
"https://api.openweathermap.org/data/2.5/weather?q=berlin&appid=240ef553958220e0d857212bc790cd14"
)
.then(res => {
this.setState({
content: [
{
coord: res.data.coord
},
{ base: res.data.base }
]
});
});
}
render() {
console.log(this.state.content.coord);
return (
<div className="App center">
<h2 className="blue-text">Weather App</h2>
<div></div>
<Weather />
</div>
);
}
}
export default App;
JSON endpoint goes here....
{
"coord": {
"lon": 13.41,
"lat": 52.52
},
"weather": [
{
"id": 803,
"main": "Clouds",
"description": "broken clouds",
"icon": "04n"
}
],
"base": "stations",
"main": {
"temp": 276.88,
"feels_like": 268.47,
"temp_min": 275.37,
"temp_max": 278.15,
"pressure": 994,
"humidity": 80
},
"visibility": 10000,
"wind": {
"speed": 9.3,
"deg": 240,
"gust": 14.4
},
"clouds": {
"all": 75
},
"dt": 1580260557,
"sys": {
"type": 1,
"id": 1275,
"country": "DE",
"sunrise": 1580280826,
"sunset": 1580312685
},
"timezone": 3600,
"id": 2950159,
"name": "Berlin",
"cod": 200
}
As content is an array type you can access coord or base directly. Instead change it to an object or access it based on array index like this.
this.state.content[0].coord / this.state.content[1].base
If you change content to object type you can access coord or base directly as i did it here
sample code:
state = {
content: { coord: "", base: "" }
};
after request fetch you can update state something like this.
this.setState({
content: { coord: res.data.coord, base: res.data.base }
});
You can make your state look like below which make reading and accessing the data easier.
state = {
content: {
coord: "",
base: "",
},
}
and your setState like below:
this.setState({
content: {
coord: res.data.coord,
base: res.data.base
}
})
Consider that i have the normalized object like this in redux store
{
"entities": {
"listings_by_id": {
"1": {
"id": 1,
"address": "991 Folsom St, San Francisco, CA 94107, USA",
"info": "Triplex 4,000 sqft",
"cap": "7.1",
"position": {
"lat": 37.778519,
"lng": -122.40564
}
},
"2": {
"id": 2,
"address": "1139004, San Francisco, CA 94118, USA",
"info": "Duplex 1,500 sqft",
"cap": "6.8",
"position": {
"lat": 37.768519,
"lng": -122.43564
}
}
}
},
"result": [
1,
2
]
}
In want to display the property list in the UI. Something like
Triplex 4,000 sqf
CAP RATE: 7.1
Duplex 1,500 sqft
CAP RATE: 6.2
Do i need to denormalize again for displaying in UI? If yes, where do i handle this - mapStateToProps?
Any help would be much appreciated.
You can add result into mapStateToProps and then iterate it like this
return this.props.result.map(a=>{
return <><div>{state.entities.listings_by_id[a].info}</div><div>{state.entities.listings_by_id[a].cap}</div></>
})
Here result should be mapped like this
const mapStateToProps = (state) => ({
result:state.reducername.result
});
and state.entities is the store
import store from 'path/ReactReducers/store';
state.entities should be replaced as store.getState().reducername.
As Justcode said above, the best way is handle that on mapStateToProps function. I created a codepen to show you how to do it. https://codepen.io/aquilesb/pen/bOKrzP
//Import any modules from libraries
const { Provider, connect } = ReactRedux;
const { createStore } = Redux;
// initial state
const initialState = { test:{
"entities": {
"listings_by_id": {
"1": {
"id": 1,
"address": "991 Folsom St, San Francisco, CA 94107, USA",
"info": "Triplex 4,000 sqft",
"cap": "7.1",
"position": {
"lat": 37.778519,
"lng": -122.40564
}
},
"2": {
"id": 2,
"address": "1139004, San Francisco, CA 94118, USA",
"info": "Duplex 1,500 sqft",
"cap": "6.8",
"position": {
"lat": 37.768519,
"lng": -122.43564
}
}
}
},
"result": [
1,
2
]
}};
// create store
let store = createStore(state => state, initialState);
const ReduxTextField = ({ entities }) =>(
<ul>
{ Object.entries(entities).map((entity) =>(
<li>
<div><span style={{marginRight:'10px'}}>Info:</span>{entity[1].info}</div>
<div><span style={{marginRight:'10px'}}>CAP:</span>{entity[1].cap}</div>
</li>
))}
</ul>)
const mapStateToProps = function (state) {
return {
entities: state.test.entities.listings_by_id
}
}
//shorter way to write mapStateToProps
//const mapStateToProps = state => ({ entities: state.test.entities.listings_by_id })
const ReduxTextFieldContainer = connect(mapStateToProps, null)(ReduxTextField);
//Create teh app component which contains the button and text field
class App extends React.Component {
render() {
return (
<div>
<ReduxTextFieldContainer />
</div>
)
}
}
//Finally render to DOM!
ReactDOM.render(<Provider store={store}><App/></Provider>, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/6.0.0/react-redux.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.1/redux.min.js"></script>
<div id="root"></div>
How to call the data from json in angularjs form without using backend. i have written this code and here m unable to find a way in last to get data from the json file. someone please help me to move forward from here.
code
$scope.count = $scope.newPreAuth.length;
};
//Delete newPreAuth - Using AngularJS splice to remove the preAuth row from the newPreAuth list
//All the Update newPreAuth to update the locally stored newPreAuth List
//Update the Count
$scope.deletenewPreAuth = function (preAuth) {
$scope.newPreAuth.splice($scope.newPreAuth.indexOf(preAuth), 1);
getLocalStorage.updatenewPreAuth($scope.newPreAuth);
$scope.count = $scope.newPreAuth.length;
};
}]);
//Create the Storage Service Module
//Create getLocalStorage service to access UpdateEmployees and getEmployees method
var storageService = angular.module('storageService', []);
storageService.factory('getLocalStorage', function () {
var newPreAuthList = {};
return {
list: newPreAuthList,
updatenewPreAuth: function (newPreAuthArr) {
if (window.localStorage && newPreAuthArr) {
//Local Storage to add Data
localStorage.setItem("newPreAuth", angular.toJson(newPreAuthArr));
}
newPreAuthList = newPreAuthArr;
},
getnewPreAuth: function () {
//Get data from Local Storage
newPreAuthList = angular.fromJson(localStorage.getItem("newPreAuth"));
return newPreAuthList ? newPreAuthList : [];
}
};
});
Json Code
PreAuth:
======================
URL:http://dev.xxx.com:8080/xxx/preAuth
TYPE:POST
X-Auth-Token t3Z10HGEiYFdzq9lGtr18ycdeAAXmWBEI64rQAJcAte6Ka8Tz96IAhuXHSgpiKufsd
{
"preAuth": {
"claimbId": "newPreAuth",
"claimbStatus": "new",
"patientInfo": {
"patientName": "name",
"gender": "Male",
"dob": 950639400000,
"age": 21,
"contactNumber": 9987654356,
"tpaMemberId": 950639400121,
"policyNumber": "ABC12615627",
"corporateName": "ABC",
"EmployeeId": "XYZ10232",
"otherInsurance": {
"isOtherInsurance": true,
"playerName": "xyx",
"details": "sdfdsafdsfdsf"
},
"familyPhysician": {
"isFamilyPhysician": true,
"physicianName": "fsdf"'c
"physicianContactNumber": 7878748728,
"address": {
"address1": "Hosa road",
"address2": "Basapura",
"city": "Bangalore",
"state": "Karnataka",
"country": "India",
"pincode": "560100"
}
},
"isFamilyPhysician": false,
"address": {
"address1": "Hosa road",
"address2": "Basapura",
"city": "Bangalore",
"state": "Karnataka",
"country": "India",
"pincode": "560100"
}
},
"medicalInfo": {
"illnessType": "cancer",
"clinicalFinding": "description",
"ailmentDuration": "2 months",
"ailmentHistory": "description",
"illnessCause": "alcohol",
"provisionalDiagnosis": [
{
"diagnosisName": "abc",
"diagnosisICDCode": "121423"
},
{
"diagnosisName": "xyz",
"diagnosisICDCode": "434543"
}
],
"differentialDiagnosis": [
{
"diagnosisName": "afasdbc",
"diagnosisICDCode": "12431423"
},
{
"diagnosisName": "fdxyz",
"diagnosisICDCode": "434sdf543"
}
],
"clinicalObservations": {
"BP": "120/80",
"CVS": "126",
"P.A.": "abc",
"R.S.": "aa",
"CNS": "dd",
"others": "others"
},
"maternityDetails": {
"maternityType": "G",
"L.M.P.": 950639400000,
"E.D.D.": 950639400000
},
"accidentDetails": {
"accidentCause": "xyz",
"accidentDate": 950639400000,
"isPoliceComplaint": true,
"firNumber": "asfsafds"
},
"pastIllness": [
{
"pastIllnessType": "Diabetes",
"isPresent": true,
"NoOfMonth": 2,
"NoOfYear": 5,
"illnessSince": 950639400000
},
{
"pastIllnessType": "Hypertension",
"isPresent": true,
"NoOfMonth": 2,
"NoOfYear": 5,
"illnessSince": 950639400000
},
{
"pastIllnessType": "Other",
"isPresent": false,
"NoOfMonth": 2,
"NoOfYear": 5,
"illnessSince": 950639400000
}
]
},
"treatmentInfo": {},
"billingInfo": {},
"documents": [
{
"documentId": 12345,
"documentMetadata": {
"documentName": "discharge summary",
"date": 950639400000,
"version": "1.1",
"viewedStatus": false,
"link": "link to view/download document"
}
},
{
"documentId": 12346,
"documentMetadata": {
"documentName": "medical summary",
"date": 950639400000,
"version": "1.0",
"viewedStatus": true,
"link": "link to view/download document"
}
}
]
}
}
I created sample ,it worked this way
// Code goes here
var app = angular.module('app',[]);
app.controller('sample', function($scope,$http){
$scope.name = "advaitha";
$http.get('test.json').then(function(data){
console.log(data.data);
});
})
here is the plunker example
using HTML5 localStorage would require you to serialize and deserialize your objects before using or saving them.
For example:
var myObj = {
firstname: "kisun",
lastname: "rajot",
website: "https://www.kisun.com"
}
//if you wanted to save into localStorage, serialize it
window.localStorage.set("empData", JSON.stringify(myObj));
//unserialize to get object
var myObj = JSON.parse(window.localStorage.get("empData"));
Created a plunker based on your code am able save and retrieve the json data with your code. Please check here
Try create Leaflet Map with clustering markers in my app. Using for this Angular Leaflet Directive plugin.
It's work with example controller and JSON data, but I have other JSON with other data format and have problem with get lattitude and longitude parameters for creating markers array on my map.
My Controller
app.controller("BasicFirstController", [ "$scope", "$http", function($scope, $http) {
var addressPointsToMarkers = function(points) {
return points.map(function(ap) {
return {
layer: 'realworld',
lat: ap[0],
lng: ap[1],
message: ap[2]
};
});
};
angular.extend($scope, {
center: {
lat: 53.13207624721133,
lng: 26.01689853383789,
zoom: 15
},
events: {
map: {
enable: ['moveend', 'popupopen'],
logic: 'emit'
},
marker: {
enable: [],
logic: 'emit'
}
},
layers: {
baselayers: {
osm: {
name: 'OSM',
url: 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
type: 'xyz'
},
overlays: {
realworld: {
name: "Real world data",
type: "markercluster",
visible: true
}
}
}
});
$http.get("sample.json").success(function(data) {
$scope.markers = addressPointsToMarkers(data);
});
}]);
Work with this JSON format
[
[-37.8839, 175.3745188667, "571"],
[-37.8869090667, 175.3657417333, "486"],
[-37.8894207167, 175.4015351167, "807"],
[-37.8927369333, 175.4087452333, "899"],
[-37.90585105, 175.4453463833, "1273"]
]
Need work with this JSON format
{
"posts": [
{
"ID": "1",
"title": "Title",
"tag": "tag1",
"lat": "53.11691211703813",
"lng": "26.03631556034088",
"thumb": "getImage-24-100x100.jpg",
"fullimg": "getImage-24.jpg",
"imgs": [
{
"imgurl": "getImage-24-300x200.jpg"
}
],
"place": "Place",
"type": "Photo",
"period": "War",
"year": "1985",
"url": "site.com",
"author": "author"
},
{
"ID": "2",
"title": "Title2",
"tag": "tag2",
"lat": "53.11691211703813",
"lng": "26.03631556034088",
"thumb": "getImage-24-100x100.jpg",
"fullimg": "getImage-24.jpg",
"imgs": [
{
"imgurl": "getImage-24-300x200.jpg"
}
],
"place": "Place",
"type": "Photo",
"period": "War",
"year": "1935",
"url": "site.com",
"author": "author"
}
]
}
How get data with lat and lng from JSON for markers array?
Here is what worked for me with a JSON file sent from server, to publish ALL markers at once:
Then with $HTTP I can "get" the data, but you will have to loop through it and push details to a new $scope array:
$scope.markers = []
$http.get('JSONfilePath').then(function (responseData) {
for (var i = 0; i < responseData.data.length; i++){
$scope.markers.push({
lat: responseData.data[i].latitude,
lng: responseData.data[i].longitude
})
}
})
In the HTML file, it's pretty straight forward:
<leaflet lf-center="center" defaults="defaults" markers="markers" width="90%" height="800px"></leaflet>