REST calls from a react component - json

I'm trying to replicate same code here with different JSON, but the data is not loading.
Please help, I'm not sure what is missing in the code.
import React from 'react';
export default class ItemLister extends React.Component {
constructor() {
super();
this.state = { items: [] };
}
componentDidMount() {
fetch('http://media.astropublications.com.my/api/drebar_landing.json')
.then(result=>result.json())
.then(items=>this.setState({items}));
}
render() {
return(
<ul>
{this.state.items.length ?
this.state.items.map(item=><li key={item.id}>{item.Title}</li>)
: <li>Loading...</li>
}
</ul>
)
}
}

Your api response contains an object ArticleObject and the ArticleObject has array of objects so you need to set the items.ArticleObject to the state.
Take a look at below solution for better understanding
componentDidMount() {
fetch('http://media.astropublications.com.my/api/drebar_landing.json')
.then(result=>result.json())
.then(items=>this.setState({items:items.ArticleObject}));
}

Related

Passing props through a "template" component

I'm building a template component using React with TypeScript but i'm facing an issue i'm unable to solve. I'm posting this in case anyone knows how to approach it.
My project has a MyComp component that invokes TemplateComp using a subcomponent GraphComp and the data that Graph requires.
TemplateComp invokes and stylises the Graph subcomponent plus adds some props that are needed (such as customPropertyA) next to graphData.
GraphComp is requiring certain parameters that graphData needs to render properly.
The issue i'm facing is related to the types definition from GraphComp to MyComp while passing through TemplateComp. It may seem that (because TemplateComp defines graphData as any, as it is unknown to it) MyComp understands that graphData can also be any, but in reality it should be equal to the properties that Graph is requiring as Props (but not all of them).
Is there any way to let MyComp and TemplateComp infer the types that GraphComp is asking for?
Here is my code:
import { Component, ElementType } from 'react'
export default class MyComp extends Component<{}, {}> {
render() {
return (
<div>
<TemplateComp
Graph={GraphComp}
graphData={{
value: 0
}}
/>
</div>
)
}
}
class TemplateComp extends Component<
{
Graph: ElementType
graphData: any
},
{}
> {
customPropertyA = 'hello'
render() {
const { graphData, Graph } = this.props
return (
<div>
<Graph {...graphData} customPropertyA={this.customPropertyA} />
</div>
)
}
}
class GraphComp extends Component<
{
value: number
customPropertyA: string
},
{}
> {
render() {
return <div>my value: {this.props.value}</div>
}
}
I'm perfectly fine with modifying how these components work. However, i still need the 3 layer approach and to be able to define GraphComp's props from within MyComp and TemplateComp separately.
For those wondering how to approach this, i managed to fix it by calling the mounted JSX instead of mounting it in TemplateComp and removed properties from it as they can also be described in MyComp.
import { Component, ElementType } from 'react'
export default class MyComp extends Component<{}, {}> {
render() {
return (
<div>
<TemplateComp
Graph={<GraphComp value={0} customPropertyA={"hello"} />}
/>
</div>
)
}
}
class TemplateComp extends Component<
{
Graph: JSX.Element
},
{}
> {
render() {
const { Graph } = this.props
return (
<div>
{Graph}
</div>
)
}
}
class GraphComp extends Component<
{
value: number
customPropertyA: string
},
{}
> {
render() {
return <div>my value: {this.props.value}</div>
}
}

How retrieve data from an API in JSON to a list in React.Js

I am trying to retrieve data from an API in React.Js but there is an small issue with the componentDidMount function.
Here is the API https://projects.cmsbox.in/app/bms/movie/public/api/upcomingMovie
I have tried this code with other API and it worked but in this case its not working. Also checked the API in Postman and everything seems to be fine.
Thanks in advance :)
import React, { Component } from 'react';
import './index.css';
import MovieCard from './moviecard'
import Homepage from './homepage';
import { render } from '#testing-library/react';
class UpcommingMovies extends Component{
constructor(props){
super(props);
this.state = {
upcmngmovie_list: [],
dataList:[],
isLoaded:false,
}
}
componentDidMount(){
fetch('https://projects.cmsbox.in/app/bms/movie/public/api/upcomingMovie')
.then(response=>response.json())
.then(data=>{
this.setState({
isLoaded:true,
dataList:data,
upcmngmovie_list:dataList,
})
});
}
render(){
var{isLoaded,upcmngmovie_list}=this.state;
function upcomngmoviecards(val){
return(
<div className="row"><MovieCard image={val.image} movie_name={val.movie_name}/></div>
);
}
if(!isLoaded){
return <div>Loading...</div>;
}
else{
return (
<>
<Homepage />
<div className="main">
<h3>Upcomming Movies</h3>
<div className="cardlist">
{upcmngmovie_list.map(upcomngmoviecards)}
</div>
</div>
</>
)
}
}
}
export default UpcommingMovies;
The api does not return an array it is returning an object. Array is in "Movie_list" property. Update your set state function to use the property.
this.setState({
isLoaded:true,
dataList:data,
upcmngmovie_list:data.Movie_list,
})

Invoke function from React component declared as variable

How to invoke React component's function when this component is given in variable? I have a Parent that passes Test class into Child component, and this child wants to change something in Test.
export class Parent extends React.Component {
render() {
let test = (<Test />);
return (<Child tester={test} />);
}
}
export class Child extends React.Component {
render() {
this.props.tester.setText("qwerty"); // how to invoke setText, setState or something like that?
return ({this.props.tester});
}
}
export class Test extends React.Component {
constructor(props) {
super(props);
this.state = {
text: this.props.text || ""
};
}
setText(text) {
this.setState({ text: text });
}
render() {
return (<div>{this.state.text}</div>);
}
}
I think you should think about life cycle of react components.
Please try the code below(I just added logging), and observe logs carefully.
export class Parent extends React.Component {
render() {
let test = (<Test />);
return (<Child tester={test} />);
}
}
export class Child extends React.Component {
render() {
console.log("Child render"); // <= logging added!
// this.props.tester.setText("qwerty");
// What kind of object is 'this.props.tester(= <Test />)' here???
return ({this.props.tester});
}
}
export class Test extends React.Component {
constructor(props) {
super(props);
console.log("Test constructor"); // <= logging added!
this.state = {
text: this.props.text || ""
};
}
setText(text) {
// this.setState({ text: text });
// this is another problem. We cannot call setState before mounted.
this.state.text= text;
}
render() {
return (<div>{this.state.text}</div>);
}
}
If so, you will see 2 important facts.
'Test' component is not instantiated yet, when you call 'setText'.
How can we call a method of object which is not instantiated? Cannot!
this means 'this.props.tester' is not an instance of 'Test' component.
But if you really want to exec your code, modify Child.render like this.
render() {
var test = new Test({props:{}});
// or even this can work, but I don't know this is right thing
// var test = new this.props.tester.type({props:{}});
test.setText("qwerty");
return test.render();
}
But I don't think this is a good way.
From another point of view, one may come up with an idea like,
render() {
// Here, this.props.tester == <Test />
this.props.tester.props.text = "qwerty";
return (this.props.tester);
}
but of course it's not possible, because 'this.props.tester' is read-only property for Child.

How to access JSON in a React Component?

I have a JSON object from a script tag like so:
<script type="text/json" id="json-data">
{'someData': 'Lorem ipsum...'}
</script>
I would like to be able to pull this information and use it within a React component in my render method.
The issue seems to be that I need to set this to a variable within componentWillMount:
export default MyReactComponent extends Component {
componentWillMount() {
const test = document.getElementById('json-data').innerHTML;
}
render() {
return (
<div>
// This is where I would like to use this data.
</div>
);
}
}
Is this the best way to handle passing this data? If so, how can I access this data within the render method of my component?
Thanks!
Store it in the component's state. The render method should only depend this.state and this.props
At the risk of oversimplifying:
this.props are passed from parent components
this.state is state that is internal to the component
Example
export default MyReactComponent extends Component {
componentDidMount() {
this.setState({
test: JSON.parse(document.getElementById('json-data').innerHTML)
});
}
render() {
return <div>{this.state.test}</div>;
},
getInitialState: function() {
return {test: {}}
}
}

React-router transitionTo is not a function

import React from 'react';
import { Router, Link, Navigation } from 'react-router';
export default class ResourceCard extends React.Component {
render() {
return (
<div onClick={this.routeHandler.bind(this)}>
LINK
</div>
);
}
routeHandler(){
this.transitionTo('someRoute', {objectId: 'asdf'})
}
}
I can't get it, what's wrong?
I'm receiving an error:
Uncaught TypeError: this.transitionTo is not a function
I've tried everything I've find in docs or in gitHub issues:
this.transitionTo('someRoute', {objectId: 'asdf'})
this.context.transitionTo('someRoute', {objectId: 'asdf'})
this.context.route.transitionTo('someRoute', {objectId: 'asdf'})
etc.
the route and the param is correct, it works fine in this case:
<Link to="'someRoute" params={{objectId: 'asdf}}
p.s. react-router, react and other libraries is up to date
The Navigation component is a Mixin and needs to be added to the component accordingly. If you want to bypass the Mixin (which I feel is the direction React-Router is going) you need to set the contextTypes on the component like so:
var ResourceCard = React.createClass({
contextTypes: {
router: React.PropTypes.func
}, ...
then you can call this.context.router.transitionTo.
This works with react 0.14.2 and react-router 1.0.3
import React from 'react';
import { Router, Link } from 'react-router';
export default class ResourceCard extends React.Component {
constructor(props,) {
super(props);
}
render() {
return (
<div onClick={this.routeHandler.bind(this)}>
LINK
</div>
);
}
routeHandler(){
this.props.history.pushState(null, '/');
}
}
As there's no mixin support for ES6 as of now , you need to change a few things to make it work .router is an opt-in context type so you will have to explicitly define contextTypes of the class . Then in your constructor You will have to pass context and props to super class. And while calling transitionTo you'll have to use this.context.router.transitionTo . and you don't need to import Navigation.
import React from 'react';
import { Router, Link } from 'react-router';
export default class ResourceCard extends React.Component {
constructor(props, context) {
super(props, context);
}
render() {
return (
<div onClick={this.routeHandler.bind(this)}>
LINK
</div>
);
}
routeHandler(){
this.context.router.transitionTo('someRoute', {objectId: 'asdf'})
}
}
ResourceCard.contextTypes = {
router: function contextType() {
return React.PropTypes.func.isRequired;
}
};