I am serving some content from my API.
I want display response from API in my react component.
Response is html with bundled all assets inline by webpack.
How can I do it?
I tried dangerouslySetInnerHTML but it crashes my javascript inside returned html.
My cmp :
import React, { Component } from 'react';
import axios from 'axios';
export default class Report extends Component {
constructor() {
super();
this.state = {
id: null,
report: null
};
}
getParam(param){
return new URLSearchParams(window.location.search).get(param);
}
componentWillMount() {
axios.post(`/url`,
{
'id': this.getParam('id'),
}
)
.then(res => {
this.setState({id: res.data});
setTimeout(() => {
axios.get(`https://rg.ovh/`+this.state.id)
.then(res => {
this.setState({report: res.data})
});
}, 1900);
});
}
render() {
return (
<div dangerouslySetInnerHTML={ {__html: this.state.report} } />
);
}
}
import axios from 'axios';
import React, { Component } from 'react';
import renderHTML from 'react-render-html';
class App extends Component {
constructor() {
super();
this.state = {
htmlString: ''
};
}
componentDidMount() {
axios.get('http://localhost:5000').then(response => {
this.setState({ htmlString: response.data })
}).catch(err => {
console.warn(err);
});
}
render() {
const { htmlString } = this.state;
return (
<div className="App">
{renderHTML(htmlString)}
</div>
);
}
}
export default App;
Related
I have two classes, App and qrCode. The qrCode class returns a image of the qrcode based on the address provided in that classes state. The app class displays the qrcode component. In the method getSessionID, the app makes a request to the server, then should call updateQrCode to update the qrcode that is being shown.
How can I call the method updateQrCode from App.js? I can't instantiate a new QrCode, because that is not the instance that is being displayed.
App.js:
import React, { Component } from "react";
import "./App.css";
import QrCode from "../qrCode/qrCode";
class App extends Component {
constructor(props) {
super(props);
}
render() {
return (
<div className="App">
<header className="App-header">
<QrCode />
</header>
</div>
);
}
getSessionID() {
fetch("/getSessionID")
.then((res) => {
// code here to update the qr code in the instance of QrCode
// QrCode.updateQrCode("test")
})
.then((data) => console.log(data.message));
}
}
export default App;
QrCode.js:
import "./qrCode.css";
import QRCode from "qrcode";
import React, { Component } from "react";
class QrCode extends Component {
constructor(props) {
super(props);
this.state = {
qrCode: {
address: null,
image: null,
},
};
}
componentDidMount() {
generateQrCode(this.state.qrCode.address).then(
function (image) {
this.setState({
qrCode: {
address: this.state.qrCode.address,
image: image,
},
});
}.bind(this)
);
}
updateQrCode = () => {
this.setState({
qrCode: {
address: "asdf",
image: null,
},
});
};
render() {
return (
<div>
<img src={this.state.qrCode.image} alt="QR Code"></img>
</div>
);
}
}
function generateQrCode(address) {
return new Promise(function (resolve, reject) {
if (address) {
QRCode.toDataURL(address, {
errorCorrectionLevel: "h",
color: {
dark: "#000000",
light: "#0000",
},
})
.then((dataURI) => {
resolve(dataURI);
})
.catch((err) => {
console.error(err);
reject(err);
});
} else {
return address;
}
});
}
export default QrCode;
App.js is the parent component and QrCode.js is the child component. From parent to child you can pass by props directly.
In App.js, create a state object and update it on receiving fetch response. React re-renders component and its children whenever state object changes.
App.js
import React, { Component } from "react";
import "./App.css";
import QrCode from "../qrCode/qrCode";
class App extends Component {
constructor(props) {
super(props);
this.state = { qrCodeImage: null};
}
render() {
return (
<div className="App">
<header className="App-header">
<QrCode qrCodeImage={this.state.qrCodeImage} />
</header>
</div>
);
}
getSessionID() {
fetch("/getSessionID")
.then((res) => {
// code here to update the qr code in the instance of QrCode
// QrCode.updateQrCode("test")
})
.then((data) => this.setState({ qrCodeImage:data }));
}
}
export default App;
QrCode.js
updateQrCode = () => {
this.setState({
qrCode: {
address: "asdf",
image: this.props.qrCodeImage,
},
});
};
I have been trying to setup a redirect if a query returns a 400 status {order not found} or if the query doesn't return anything. However, as soon as I add the status code check it gives this error:
Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method.
in OrderTracking (created by Context.Consumer)
import React, { Component } from 'react'
import TrackingRender from '../TrackingRender/TrackingRender'
export class OrderTracking extends Component {
constructor() {
super()
this.state = {
order: []
}
}
async componentDidMount() {
this._isMounted = true;
const { id } = this.props.match.params
const response = await fetch(`http://localhost:5000/api/orders/${id}`)
const data = await response.json()
if (!data || response.status == 400) {
await this.props.history.push('/orders')
}
this.setState({
order: data
})
console.log(this.state)
}
render() {
return (
<div>
< TrackingRender order={this.state.order} />
</div>
)
}
}
export default OrderTracking
Never mind! Used axios and reread some documentation on the error. Here is the updated code if anybody is interested or has the same error in the future.
import React, { Component } from 'react'
import TrackingRender from '../TrackingRender/TrackingRender'
import axios from 'axios'
import { Redirect } from 'react-router';
export class OrderTracking extends Component {
constructor() {
super()
this.state = {
loadingData: true,
order: []
}
}
async componentDidMount() {
this._isMounted = true;
if (this.state.loadingData) {
try {
const { id } = this.props.match.params
const response = await axios.get(`http://localhost:5000/api/orders/${id}`)
const data = await response.json()
this.setState({
order: data,
loadingData: false
})
console.log(this.state)
} catch (err) {
console.log(err)
}
}
}
render() {
if (!this.state.loadingData) {
return (
<div>
< TrackingRender order={this.state.order} />
</div>
)
} else {
return (
<Redirect to='/orders' />
)
}
}
}
export default OrderTracking
import React, { Component } from 'react';
import TrackingRender from '../TrackingRender/TrackingRender';
export class OrderTracking extends Component {
constructor() {
super();
this.state = {
order: [],
};
}
componentDidMount() {
var _this = this;
this._isMounted = true;
const { id } = this.props.match.params;
fetch(`http://localhost:5000/api/orders/${id}`)
.then((response) => {
if (response.ok) {
_this.setState({
order: data,
});
} else {
if (res.status === 400) {
this.props.history.push('/orders');
}
}
})
.then((data) => console.log('data is', data))
.catch((error) => console.log('error is', error));
}
render() {
return (
<div>
<TrackingRender order={this.state.order} />
</div>
);
}
}
export default OrderTracking;
I have an issue in figuring in what conditions props are not passed down by the tree. I have a Fetcher class in which I populate with "layouts", then pass it to children props, but I cannot access it from child component.
EX:
import React, { Component } from 'react'
import axios from "axios";
export default class Fetcher extends Component {
constructor(props) {
super(props)
this.state = {
layouts: [],
}
componentDidMount() {
this.getLayouts();
}
getLayouts = () => {
axios
.get("/layout")
.then((res) => {
this.setState({
layouts: res.data,
});
})
.catch((err) => console.log(err));
};
render() {
return (
this.props.children(this.state.layouts)
)
}
}
This is my Parent component on which I pass some props children:
ex:
import React, { Fragment } from "react";
import Fetcher from "./Fetcher";
class App extends Component {
<Fetcher>
{(layouts) => {
return <Fragment>
<NewLayout
layoutsList={layouts} />
</Fragment>
}}
</Fetcher>
}
import React from "react";
class NewLayout extends React.Component {
constructor(props) {
super(props)
this.state = {
layouts: [],
}}
componentDidMount() {
this.setState(() => ({
layouts: this.props.layoutList
}))
}
render() {
{ console.log(this.state.layouts) }
{ console.log(this.props.layoutList) }
return (
....
The children prop is not a function, if you want to pass a property to it you should use React.Children API with React.cloneElement:
class Fetcher extends Component {
state = {
layouts: [/*some layout values*/],
};
render() {
const children = this.props.children;
const layouts = this.state.layouts;
return React.Children.map(children, (child) =>
React.cloneElement(child, { layouts })
);
}
}
Typo my friend, looks like you pass layoutsList prop to NewLayout, but internally use layoutList.
I have initiated a state in _app.js using Next.js.
I would like to use this state in the index.js file.
How can I access it?
This is my _app.js code:
import React from 'react';
import App, { Container } from 'next/app';
import Layout from '../components/Layout';
export default class MyApp extends App {
constructor(props) {
super(props);
this.state = {
currencyType: {
name: 'Ether',
price: 1,
},
ethPriceUsd: 1,
};
}
static async getInitialProps({ Component, router, ctx }) {
let pageProps = {};
let ethPriceUsd;
if (Component.getInitialProps) {
fetch(`https://api.coingecko.com/api/v3/coins/ethereum/`)
.then((result) => result.json())
.then((data) => {
ethPriceUsd = parseFloat(data.market_data.current_price.usd).toFixed(
2
);
});
pageProps = await Component.getInitialProps(ctx);
}
return { pageProps, ethPriceUsd };
}
componentDidMount() {
const ethPriceUsd = this.props.ethPriceUsd;
this.setState({ ethPriceUsd });
}
onCurrencyTypeChange(currencyTypeValue) {
let currencyType = {};
//Value comes from Header.js where Ether is 0 and USD is 1
if (currencyTypeValue) {
currencyType = {
name: 'USD',
price: this.state.ethPriceUsd,
};
} else {
currencyType = {
name: 'Ether',
price: 1,
};
}
alert('We pass argument from Child to Parent: ' + currencyType.price);
this.setState({ currencyType });
}
render() {
const { Component, pageProps } = this.props;
return (
<Container>
<Layout changeCurrencyType={this.onCurrencyTypeChange.bind(this)}>
<Component {...pageProps} />
</Layout>
</Container>
);
}
}
A lot of it is irrelevant (Like passing the data to the Layout etc...). All I want to do is use this state in my index.js.
let's say you have this code in _app.js.
import React from 'react'
import App, { Container } from 'next/app'
export default class MyApp extends App {
static async getInitialProps({ Component, router, ctx }) {
let pageProps = {}
if (Component.getInitialProps) {
pageProps = await Component.getInitialProps(ctx)
}
return { pageProps }
}
state = {
name: "Morgan",
}
render () {
const { Component, pageProps } = this.props
return (
<Container>
<Component {...pageProps} {...this.state}/>
</Container>
)
}
}
Please notice the state and <Component {...pageProps} {...this.state}/>
Solution 1:
Now, let's see how can we use it in index.js or any other pages
import React from 'react';
export default class Index extends React.Component {
render() {
return (
<div>
<h2>My name is {this.props.name}</h2>
</div>
)
}
}
You can use them as props like this this.props.name
Solution 2:
Populate state in the index.js from props and then access it from state
import React from 'react';
export default class Index extends React.Component {
constructor(props) {
super(props)
this.state ={
name: this.props.name
}
}
render() {
return (
<div>
<h2>My name is {this.state.name}</h2>
</div>
)
}
}
You can use them as props like this this.state.name
Here is my store:
import helper from './../../helpers/RestHelpers.js';
var posts = [];
class PostStore {
constructor() {
helper.get('/api/posts')
.then((data) => {
posts = data;
console.log(posts);
}
);
}
getPosts() {
return posts;
}
};
export default new PostStore();
When I console.log posts from within the helper function, I get the correct data. But when I console.log from the component, the array of posts is empty.
Here is my component:
import React from 'react';
import postStore from '../stores/PostStore';
class Home extends React.Component {
constructor() {
super();
this.state = {
posts: postStore.getPosts()
}
console.log(this.state.posts);
}
render() {
return (
<div className="welcome">
{this.state.posts.map(function(post, index) {
return (
<PostItem post={post} key={"post " + index} />
)
})
}
</div>
)
}
}
class PostItem extends React.Component {
render() {
return <div>{this.props.post.postName}</div>;
}
}
export default Home;
I wouldn't use your PostStore as-is. Instead just use your helper directly like so:
import React from 'react';
// import your helper!
class Home extends React.Component {
componentDidMount() {
helper.get('/api/posts').then((data) => {
this.setState({posts: data})
});
}
render() {
return (
<div className="welcome">
{this.state.posts.map((post, idx) => <PostItem post={post} key={"post " + idx} />)}
</div>
)
}
}