Accessing normalized data in reducer - reactjs

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

Why is my react/redux function is not redering data fetched from json file?

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

I am trying to call Weather API using React and Axios I am trying to console.log the result but its saying the undefined... :(

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
}
})

Handling normalized data for displaying in the page - redux

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 fetch data from json in angularjs Form

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

Angular-Leaflet-Directive + JSON markers

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>

Resources