Why my this.state is null? - json

I'm new with React and i'm trying to render a json from a websocket.
Right now i'm able to get the json from the websocket using this :
componentWillMount() {
this.ws = new WebSocket('ws://10.77.0.79:1234')
this.ws.onmessage = e => this.setState({data: Object.values((e.data))})
this.ws.onerror = e => this.setState({ error: 'WebSocket error' })
this.ws.onclose = e => !e.wasClean && this.setState({ error: `WebSocket error: ${e.code} ${e.reason}` })
}
And then i need to map this json, right now i'm using this:
render() {
// this is my json from websocket
var json2 = {"Auth":{"status":"true","user":"gesplan","pass":"root"}}
var arr = [];
Object.keys(json2).forEach(function(key) {
arr.push(json2[key]);
});
return <ul>{arr.map(item => <MyAppChild key={item.status} label={item.status} value={item.user} pass={item.pass} />)} {this.state.data} </ul>;
}
}
class MyAppChild extends React.Component {
render() {
return <li>{this.props.label + " - " + this.props.value + this.props.pass } </li>;
}
}
With this i can render the values of the var json2.
How can i do it with my this.state.data? when i change json2 for this.state.data it return a null, but how can the state be null if i am rendering it normally?

Set your initial state to an empty array first. Append data when new data comes in:
constructor() {
this.state = {
data: []
}
}
componentWillMount() {
this.ws = new WebSocket('ws://10.77.0.79:1234')
this.ws.onmessage = e => this.setState({
data: [].concat(this.state.data, JSON.parse(e.data).Auth)
})
this.ws.onerror = e => this.setState({ error: 'WebSocket error' })
this.ws.onclose = e => !e.wasClean && this.setState({ error: `WebSocket error: ${e.code} ${e.reason}` })
}
render() {
return (
<ul>
{this.state.data.map(item =>
<MyAppChild key={item.status} label={item.status} value={item.user} pass={item.pass} />)
}
</ul>
);
}

Related

How to get All JSON object from local JSON file in React functional component?

I'm using functional component and I'm getting JSOS object from local file And in component I'm setting that JSON in some state.
After that few object I spliced(deleted) from that setState. But again in onchange function I want all the JSON object but here I'm getting updated json means few are deleted, Is there any method I can store all JSON object in some place? can anybody help me in this.
const StudyDetails = () => {
const [supplyPlan, setSupplyPlan] = useState([]);
const getSupplyPlanDetails = useCallback(
async () => {
try {
const payload = {
studyName: studyDetails?.studyName
? studyDetails?.studyName
: query.get("name"),
country: [],
depot: [],
material: [],
site: [],
inTransientMaterial,
};
const res = await getSupplyPlan(payload);
//setSupplyPlan(res);
console.log(res)
// setSupplyPlan(supplyData)
} catch (err) {
setSupplyPlan([]);
}
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[]
);
useEffect(() => {
getSupplyPlanDetails();
}, [ getSupplyPlanDetails]);
const onChange = (e) => {debugger
console.log(supplyData)
}
return (
<div>
<Checkbox
onChange={onChange}
>
In Transit
</Checkbox>
{supplyPlan?.map((item, index) => (
<Fragment key={index}>
<SupplyChain item={item} />
<Divider className="supply-chain-divider" />
</Fragment>
))}
</div>
)
}
I'm splicing few object in supplyChain component:
const SupplyChain = ({ item }) => {
useEffect(() => {
let data = [];
if (item && item.inTransit.length != 1) {
item &&
item.inTransit &&
item.inTransit.length > 0 &&
item.inTransit.map((intrans, index) => {
if (
intrans.from === item.depots?.packagingDepot?.[0]?.depotName &&
intrans.to === "sites"
) {
let directPath = item.inTransit.splice(index, 1);
setDirectSite(directPath);
}
setFilterJson(item.inTransit);
// eslint-disable-next-line react-hooks/exhaustive-deps
item = { ...item, filterJson: item.inTransit };
});
}
}
So if again when I click on onchange function I want all objects of JSON.
please someone help me in this

How to load data onto a React State from an API instead of local json file?

So as part of my project I'm trying to ammend this boilerplate of React-Pdf-Highlighter to accept pdf highlights from flask-api instead of a local file( the example came with a local/json import) ..
I have tried to check with console.log the fetch is not the problem, but I feel for somereason the 'testHighlights' state is not what it should be .
<<App.js>>
// #flow
/* eslint import/no-webpack-loader-syntax: 0 */
import React, { Component } from "react";
import PDFWorker from "worker-loader!pdfjs-dist/lib/pdf.worker";
import {
PdfLoader,
PdfHighlighter,
Tip,
Highlight,
Popup,
AreaHighlight,
setPdfWorker
} from "react-pdf-highlighter";
import Spinner from "./Spinner";
import Sidebar from "./Sidebar";
import testHighlights from "./test-highlights";
import type {
T_Highlight,
T_NewHighlight
} from "react-pdf-highlighter/src/types";
import "./style/App.css";
setPdfWorker(PDFWorker);
type Props = {};
type State = {
url: string,
highlights: Array<T_Highlight>
};
const getNextId = () => String(Math.random()).slice(2);
const parseIdFromHash = () =>
document.location.hash.slice("#highlight-".length);
const resetHash = () => {
document.location.hash = "";
};
const HighlightPopup = ({ comment }) =>
comment.text ? (
<div className="Highlight__popup">
{comment.emoji} {comment.text}
</div>
) : null;
const PRIMARY_PDF_URL = "https://arxiv.org/pdf/1708.08021.pdf";
const SECONDARY_PDF_URL = "https://arxiv.org/pdf/1604.02480.pdf";
const searchParams = new URLSearchParams(document.location.search);
const initialUrl = searchParams.get("url") || PRIMARY_PDF_URL;
class App extends Component<Props, State> {
state = {
url: initialUrl,
highlights: testHighlights[initialUrl]
? [...testHighlights[initialUrl]]
: []
};
state: State;
resetHighlights = () => {
this.setState({
highlights: []
});
};
toggleDocument = () => {
const newUrl =
this.state.url === PRIMARY_PDF_URL ? SECONDARY_PDF_URL : PRIMARY_PDF_URL;
this.setState({
url: newUrl,
highlights: testHighlights[newUrl] ? [...testHighlights[newUrl]] : []
});
};
scrollViewerTo = (highlight: any) => {};
scrollToHighlightFromHash = () => {
const highlight = this.getHighlightById(parseIdFromHash());
if (highlight) {
this.scrollViewerTo(highlight);
}
};
componentDidMount() {
window.addEventListener(
"hashchange",
this.scrollToHighlightFromHash,
false
);
}
getHighlightById(id: string) {
const { highlights } = this.state;
return highlights.find(highlight => highlight.id === id);
}
addHighlight(highlight: T_NewHighlight) {
const { highlights } = this.state;
console.log("Saving highlight", highlight);
this.setState({
highlights: [{ ...highlight, id: getNextId() }, ...highlights]
});
}
updateHighlight(highlightId: string, position: Object, content: Object) {
console.log("Updating highlight", highlightId, position, content);
this.setState({
highlights: this.state.highlights.map(h => {
const {
id,
position: originalPosition,
content: originalContent,
...rest
} = h;
return id === highlightId
? {
id,
position: { ...originalPosition, ...position },
content: { ...originalContent, ...content },
...rest
}
: h;
})
});
}
render() {
const { url, highlights } = this.state;
return (
<div className="App" style={{ display: "flex", height: "100vh" }}>
<Sidebar
highlights={highlights}
resetHighlights={this.resetHighlights}
toggleDocument={this.toggleDocument}
/>
<div
style={{
height: "100vh",
width: "75vw",
position: "relative"
}}
>
<PdfLoader url={url} beforeLoad={<Spinner />}>
{pdfDocument => (
<PdfHighlighter
pdfDocument={pdfDocument}
enableAreaSelection={event => event.altKey}
onScrollChange={resetHash}
// pdfScaleValue="page-width"
scrollRef={scrollTo => {
this.scrollViewerTo = scrollTo;
this.scrollToHighlightFromHash();
}}
onSelectionFinished={(
position,
content,
hideTipAndSelection,
transformSelection
) => (
<Tip
onOpen={transformSelection}
onConfirm={comment => {
this.addHighlight({ content, position, comment });
hideTipAndSelection();
}}
/>
)}
highlightTransform={(
highlight,
index,
setTip,
hideTip,
viewportToScaled,
screenshot,
isScrolledTo
) => {
const isTextHighlight = !Boolean(
highlight.content && highlight.content.image
);
const component = isTextHighlight ? (
<Highlight
isScrolledTo={isScrolledTo}
position={highlight.position}
comment={highlight.comment}
/>
) : (
<AreaHighlight
highlight={highlight}
onChange={boundingRect => {
this.updateHighlight(
highlight.id,
{ boundingRect: viewportToScaled(boundingRect) },
{ image: screenshot(boundingRect) }
);
}}
/>
);
return (
<Popup
popupContent={<HighlightPopup {...highlight} />}
onMouseOver={popupContent =>
setTip(highlight, highlight => popupContent)
}
onMouseOut={hideTip}
key={index}
children={component}
/>
);
}}
highlights={highlights}
/>
)}
</PdfLoader>
</div>
</div>
);
}
}
export default App;
<<test-highlights.js >>
const testHighlights =async () => {
const res= await fetch('http://127.0.0.1:5000/jsonapi')
const data =await res.json()
console.log(data)
this.state.testHighlights = data
return testHighlights;
}
export default testHighlights;
You can't assign state like this
this.state.testHighlights = data
You must use this.setState function to do it
this.setState({ testHighlights: data });
That is why your testHighlights state isn't what you was expected

How to Fetch Json with React-Table library

the example to which I refer is the following:
https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/sub-components
I would like to fetch a json file and pass the elements of the latter into the table instead of generating them as in the previous example.
The instructions for making fetch are clear to me but I can't understand how to integrate them in the "makeData" file.
This is my "makeData" code:
import ReactDOM from 'react-dom';
const range = len => {
const arr = []
for (let i = 0; i < len; i++) {
arr.push(i)
}
return arr
}
const newPerson = () => {
fetch('http://localhost:5000/api/azienda')
.then(res => res.json())
// .then((rows) => {
// ReactDOM.render(this.makeData(rows), document.getElementById('root'));
// });
}
export default function makeData(...lens) {
const makeDataLevel = (depth = 0) => {
const len = lens[depth]
return range(len).map(d => {
return {
...newPerson(),
subRows: lens[depth + 1] ? makeDataLevel(depth + 1) : undefined,
}
})
}
return makeDataLevel()
}
For any advice I will thank you
Create an array in the constructor ,where the data will be stored , fetch the data from the serverlink and then put it in the table
constructor(props, context) {
super(props, context);
this.state = { items: []};
}
getList = () => {
fetch("http://localhost:5000/api/azienda")
.then(res => res.json())
.then(items => this.setState({ items }))
.catch(err => console.log(err));
};
componentDidMount() {
this.getList();
}

How to get the length of the response from a fetch request?

I have got series of data that contains some objects in one array(json file) and it will be shown by react.
Here is my code:
class App extends React.Component {
constructor(props){
super(props);
this.state = {
data: [],
library:null,
perPage: 20,
currentPage: 1,
maxPage: null,
filter: ""
};
}
componentDidMount() {
fetch('/json.bc')
// Here I want to get the length of my respose
.then(response => response.text())
.then(text => {
var Maindata = JSON.parse(text.replace(/\'/g, '"'))
this.setState(state => ({
...state,
data: Maindata
}), () => {
this.reorganiseLibrary()
})
}).catch(error => console.error(error))
}
reorganiseLibrary = () => {
const { filter, perPage , data } = this.state;
let library = data;
if (filter !== "") {
library = library.filter(item =>
item.hotelinfo.hotelsearch.realname.toLowerCase().includes(filter)
);
}
library = _.chunk(library, perPage);
this.setState({
library,
currentPage: 1,
maxPage: library.length === 0 ? 1 : library.length
});
};
// Previous Page
previousPage = () =>
this.setState(prevState => ({
currentPage: prevState.currentPage - 1
}));
// Next Page
nextPage = () =>
this.setState(prevState => ({
currentPage: prevState.currentPage + 1
}));
// handle filter
handleFilter = evt =>
this.setState(
{
filter: evt.target.value.toLowerCase()
},
() => {
this.reorganiseLibrary();
}
);
// handle per page
handlePerPage = (evt) =>
this.setState({
perPage: evt.target.value
}, () => this.reorganiseLibrary());
// handle render of library
renderLibrary = () => {
const { library, currentPage } = this.state;
if (!library || (library && library.length === 0)) {
return <div class="tltnodata">no result!</div>;
}
return library[currentPage - 1].map((item, i) => (
<input type="hidden" value={item.hotelinfo.hotelsearch.hotelid} name="hotelid"/>
));
};
render() {
const { library, currentPage, perPage, maxPage } = this.state;
return (
<div className="Main-wrapper">
<div class="filter_hotelname"><input value={this.state.filter} onChange={this.handleFilter} class="hotelName" /></div>
<div class="countHotel"> <span class="numbersearch"></span> // Here I want two show the count of items </div>
<div className="wrapper-data">
{this.renderLibrary()}
</div>
<div id="page-numbers">
<div class="nexprev">
{currentPage !== 1 && (
<button onClick={this.previousPage}><span class="fa-backward"></span></button>
)}
</div>
<div className="data_page-info">
{this.state.currentPage} از {this.state.maxPage}
</div>
<div class="nexprev">
{(currentPage < maxPage) && (
<button onClick={this.nextPage}><span class="fa-forward"></span></button>
)}
</div>
</div>
</div>
);
}
}
ReactDOM.render(<App/>, document.getElementById('Result'));
I want to find the length of response from a request with fetch. Also I want to know how to find the count of items that will be shown by renderLibrary . For example in json.bc we have 4 objects I want to show 4 in numbersearch span.
Using Fetch API you can find json response item length by running below code snippet. I have also added comment in code as well.
fetch('https://jsonplaceholder.typicode.com/todos')
.then(response => {
//below method return promise based response by converting stream object to json
return response.json();
}).then(json => {
//Once succcessful callback return you can find length of number of item
console.log(json);
alert("Number of item:"+json.length)
})
fetch('https://jsonplaceholder.typicode.com/todos')
.then(response => {
//below method return promise based response by converting stream object to json
return response.json();
}).then(json => {
//Once succcessful callback return you can find length of number of item
alert(json.length)
})
You can use the length of the data array from the state to distinguish the number of items.
Since arrays start at 0, you will need to increment the count by one. Here's an example snippet below that you can use in your code sample.
<div class="countHotel"><span class="numbersearch">{this.state.data && this.state.data.length + 1}</span></div>

Angular .filter() not working on JSON response

From what I can tell, the .filter() method does not work on the response returned from .json() when there is only 1 single object in the return value. I am not sure how to go about dealing with this issue.
getFavorites() {
const userId = this.authService.getActiveUser().uid;
return this.http.get(this.databaseAddress + userId + '.json')
.map(
(response: Response) => {
return response.json();
})
.do(
(data) => {
if(data) {
this.favorites = data;
}else {
this.favorites = [];
}
})
}
this.favoritesService.getFavorites()
.subscribe(
(list: Recipe[]) => {
if(list) {
this.favoriteRecipes = list.filter(
item => item !== null
);
} else {
this.favoriteRecipes = [];
}
}
);
Error returned:
ERROR TypeError: list.filter is not a function
In case of no data returned from API, your response will be null/empty. And filter operation only works on Array type. Consider returning [] empty array from map operator.
getFavorites() {
const userId = this.authService.getActiveUser().uid;
return this.http.get(this.databaseAddress + userId + '.json')
.map(
(response: Response) => {
return response.json() || []; // return blank [] if data is null or empty
})
.do(
(data) => {
if(data) {
this.favorites = data;
}else {
this.favorites = [];
}
})
}
As you mentioned the issue here is not when response is null/empty, issue is when the response only has 1 object in it.
Just append whatever result you have to an empty array, and you are done...
getFavorites() {
const userId = this.authService.getActiveUser().uid;
return this.http.get(this.databaseAddress + userId + '.json')
.map(
(response: Response) => {
return response.json();
})
.do(
(data) => {
if(data) {
this.favorites = [].push(data);
}else {
this.favorites = [];
}
})