Can access simple react state but not props - reactjs

I'm new to React so this may be simple to fix, but I cannot access {this.props.AvgRating} in the ReviewsTotalStars.js file. I'm having to use the following state code to access a variable called ratingStars:
this.state = {
ratingStars: 3.5
};
But I don't want to use the above ratingStars, and would instead prefer to use the props.AvgRating. Why cannot I access it? Here is my simple code:
index.js:
import React, { Component } from "react";
import { render } from "react-dom";
import ReviewsLeftArea from "./ReviewsLeftArea";
import "./style.css";
const avgRating = 3.5;
class App extends Component {
constructor() {
super();
this.state = {
name: "React"
};
}
render() {
return (
<div>
<ReviewsLeftArea AvgRating={avgRating} />
</div>
);
}
}
render(<App />, document.getElementById("root"));
ReviewsLeftArea.js:
import React from "react";
import ReviewsTotalStars from "./ReviewsTotalStars";
export default class ReviewsLeftArea extends React.Component {
render() {
return (
<div>
<ReviewsTotalStars avgRating={this.props.AvgRating} />
</div>
);
}
}
ReviewsTotalStars.js:
import React from "react";
export default class ReviewsTotalStars extends React.Component {
constructor() {
super();
this.state = {
ratingStars: 3.5
};
}
render() {
return (
<div>
{this.state.ratingStars} works but this {this.props.AvgRating} doesn't
</div>
);
}
}
Thanks for any help and explanations here.

In ReviewsTotalStars you want to access:
this.props.AvgRating
But it is actually:
this.props.avgRating
By the way, you should not have a props that starts with an upper case letter

Should be simple to fix, in react, you should never create vaiables outside of the class you are working on, instead you should add them to the state object, like this:
Index.js:
import React, { Component } from "react";
import { render } from "react-dom";
import ReviewsLeftArea from "./ReviewsLeftArea";
import "./style.css";
// const avgRating = 3.5;
class App extends Component {
constructor() {
super();
this.state = {
name: "React",
avgRating: 3.5;
};
}
render() {
return (
<div>
<ReviewsLeftArea AvgRating={this.state.avgRating} />
</div>
);
}
}
render(<App />, document.getElementById("root"));
ReviewsTotalStars.js:
import React from "react";
export default class ReviewsTotalStars extends React.Component {
constructor() {
super();
this.state = {};
}
render() {
return (
<div>
{this.props.avgRating} //now this should work
</div>
);
}
}

Related

How to add additional api to a fetch component in React JS

There are 2 separate components that fetch data through api. The code below is for the first component and then there is another component that fetch other data of the same company through another api and the code of that one is exactly the same except the api link. How to fetch the data from the other api in this component so there is no need for 2 different components.
import React, { Component, Fragment } from 'react'
import axios from 'axios'
class CompanyProfile extends Component {
constructor(){
super();
this.state={
Company:[]
}
}
componentDidMount(){
axios.get('http://localhost:3000/link').then(response =>{
**/////////for example axios.get('http://localhost:3000/link2') added here.**
this.setState({Company:response.data});
});
}
render() {
const cp = this.state.Company;
const CompanyView = contact.map((cp,i)=>{
**/////then mapped here.**
return <div>
<p>{cp.name}</p>
<p>{cp.type}</p>
<p>...other data</p>
**//// and then displayed here <p>{cp.CompanyProducts.data}</p>**
</div>
});
return (
<div>
{CompanyView}
</div>
)
}
}
export default CompanyProfile
I am not sure about your question. We can use container and presentational components.
A container does data fetching and then renders its corresponding sub-component. That’s it.
Refactor the CompanyProfile component to a stateless presentational component. Pass the company data from the remote API server to it from the container component.
So that we can reuse the CompanyProfile component.
CompanyProfile.jsx:
import React, { Component } from 'react';
class CompanyProfile extends Component {
render() {
const { campany } = this.props;
const CompanyView = campany.map((cp, i) => {
return (
<div>
<p>{cp.name}</p>
<p>{cp.type}</p>
<p>...other data</p>
<p>{cp.CompanyProducts.data}</p>
</div>
);
});
return <div>{CompanyView}</div>;
}
}
export default CompanyProfile;
Parent1.tsx:
import React, { Component } from 'react';
import axios from 'axios';
import CompanyProfile from './CampanyProfile';
export default class Parent extends Component {
constructor(props) {
super(props);
this.state = {
company: [],
};
}
componentDidMount() {
axios.get('http://localhost:3000/link').then((response) => {
this.setState({ company: response.data });
});
}
render() {
return <CompanyProfile company={this.state.company} />;
}
}
Parent2.jsx:
import React, { Component } from 'react';
import axios from 'axios';
import CompanyProfile from './CampanyProfile';
export default class Parent2 extends Component {
constructor(props) {
super(props);
this.state = {
company: [],
};
}
componentDidMount() {
axios.get('http://localhost:3000/link2').then((response) => {
this.setState({ company: response.data });
});
}
render() {
return <CompanyProfile company={this.state.company} />;
}
}

How to test the map reference in a react-leaflet custom child component using Enzyme?

I've created a custom component in react-leaflet by extending MapControl. The component doesn't return anything but adds something to the map object it refers to via the props.
Custom Child Component
import { MapControl, withLeaflet } from "react-leaflet";
import * as L from "leaflet";
class Dashboard extends MapControl<any, any> {
public createLeafletElement(props: any) {}
public addDashboard() {
const dashboard = L.control({ position: "topright" });
dashboard.onAdd = function() {
this._div = L.DomUtil.create("div", "dashboard");
this._div.setAttribute("data-test", "component-dashboard");
return this._div;
};
const { map } = this.props.leaflet;
dashboard.addTo(map);
}
componentDidMount() {
this.addDashboard();
}
render() {
return null;
}
}
export default withLeaflet(Dashboard);
Parent/Map component
import React from "react";
import { Map, TileLayer } from "react-leaflet";
import Dashboard from "./Dashboard";
class MapContainer extends React.Component<any> {
public constructor(props: any) {
super(props);
}
render() {
return (
<div data-test="component-map">
<Map
center={this.props.center}
zoomSnap={this.props.zoomSnap}
zoom={this.props.zoom}
style={this.props.style}
>
<TileLayer
url={this.props.url}
attribution={this.props.attribution}
/>
<Dashboard />
</Map>
</div>
);
}
}
export default MapContainer;
While testing the child component Dashboard, how do I initialise map?
(and then check if it contains the dashboard)
I'm using Jest and Enzyme
For Jest the following example demonstrates how to:
create an instance of react-leaflet Map component
ensure a custom control (Dashboard in your case) is instantiated
Example
import React from "react";
import ReactDOM from "react-dom";
import { renderIntoDocument } from "react-dom/test-utils";
import { Map, TileLayer } from "react-leaflet";
import Dashboard from "./Dashboard";
it("Control test", () => {
class TestComponent extends React.Component {
constructor() {
super();
this.controlRef = React.createRef();
}
getControl() {
return this.controlRef.current.leafletElement;
}
render() {
return (
<Map center={[0,0]} zoom={10}>
<Dashboard ref={this.controlRef} />
</Map>
);
}
}
const component = renderIntoDocument(<TestComponent />);
const control = component.getControl();
expect(control).not.toBeNull();
});

How to pass data from one component to another ReactJS

I have two components. The first has state initialized:
import React from 'react';
class One extends React.Component {
constructor(props) {
super(props);
this.state = {
data: 'hi'
}
}
render() {
return (
<div prop={this.state.data}>{this.state.data}</div>
);
}
}
export default One;
import React from 'react';
class Two extends React.Component {
render() {
return (
<div>{this.prop}</div>
);
}
}
export default Two;
The first component prints out the state of data. How would I pass that value into my second component as a read only value and render it?
To pass the value in the second component, you have to first import it in your first component and pass the value as prop.
For example, your code might look like this:
import React from 'react';
import Two from './Two' // I am assuming One.js and Two.js are in same folder.
class One extends React.Component {
constructor(props) {
super(props);
this.state = {
data: 'hi'
}
}
render() {
return (
<div>
<div>{this.state.data}</div>
<Two value={this.state.data} />
</div>
);
}
}
export default One;
And then in the Two.js you can access the value as below:
import React from 'react';
class Two extends React.Component {
render() {
return (
<div>{this.props.value}</div>
);
}
}
export default Two;
Now, let's say, you are using your component One in App or anywhere. Whenever you will use <One/> you will get following in the browser:
hi
hi
You must call this 'Two' component into 'One' like this
One Component:
render() {
return (
<Two myProp={this.state.data} />
)
}
You can call this whatever u wish (myProp)
And read this in 'Two' component:
render() {
return (
<div>Received data from parent Component: {this.props.myProp}</div>
)
}
Before you call 'Two' component into 'One' you must import that file
import Two from './path/to/component';
Just add the following code in One component render method and pass the data as props which is read-only
import React from 'react';
import Two from '/components/Two'
class One extends React.Component {
constructor(props) {
super(props);
this.state = {
data: 'hi'
}
}
render() {
return (
<div prop={this.state.data}>{this.state.data}</div>
<Two data={this.state.data} />
);
}
}
export default One;
Then In component Two to access data add following code
import React from 'react';
class Two extends React.Component {
constructor(props){
super(props)
}
render() {
return (
<div>{this.props.data}</div>
);
}
}
export default Two;
Props will hold the object transferred from parent element
One.js
import React from 'react';
import Two from './two'
class One extends React.Component {
constructor(props) {
super(props);
this.state = {
data: 'hi'
}
}
render() {
return (
<div>{this.state.data}
<Two dto={this.state} /></div>
);
}
}
export default One;
Two.Js
import React from 'react';
class Two extends React.Component {
render() {
return (
<div>Component Two data: {this.props.dto.data}</div>
);
}
}
export default Two;

how to access parent component methods in child component like below example

//this is the parent component in ibios.js file
import React from 'react';
import ReactDOM from 'react-dom';
import axios from 'axios';
class ibios extends React.Component{
constructor(){
super();
this.sate={};
this.get = this.get.bind(this);
}
get(ur,apiurl,prametars){
prametars=prepareHeaderRequest;
return axios.get(url+apiUrl,{params:prametars})
.then(function(response){
console.log(response.data);
});
}
render(){
return(
<p>hi...</p>
);
}
}
//this is the child component chart component.js file
import React from 'react';
import ibios from '../ibios/IBIOS';
import ChartComponent from './chartcomponents';
class BarChartComponent extends ChartComponent{
constructor(props){
super(props)
this.state={};
}
componentDidMount(){
//example
var url="http://localhost:9090",apiUrl="/reports",prametrs={xyz:ramki};
var retriveResponse=this.ibios.get(url,apiUrl,prametrs)
console.log(retriveResponse);
}
render(){
return(<p>hi......</p>);
}
}
// i have write axios method only once in ibos.js and how to inherit every componet and how to get response directily through ibos.get()?....................................................................................................................................................................................................................................................................................................................
class First extends React.Component {
first() {
alert("First")
}
render() {
return <div>sdfsdf</div>
}
}
class Second extends First {
second() {
alert('Second')
}
render() {
return <div>dsfsdfsdf</div>
}
}
class Third extends Second {
onButtonClick() {
super.second()
super.first()
}
render() {
return <button onClick={() => {this.onButtonClick()}}>Hello</button>;
}
}
ReactDOM.render(
<Third />,
document.getElementById('container')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="container"></div>
You should extend 'ibios' class instead of Chart Component in your child component and use keyword 'super' to use parent methods. Otherwise you can send it as props and use it
class BarChartComponent extends Ibios{
constructor(props){
super(props)
this.state={};
}
componentDidMount(){
//example
var url="http://localhost:9090",apiUrl="/reports",prametrs={xyz:ramki};
var retriveResponse=super.get(url,apiUrl,prametrs)
console.log(retriveResponse);
}
render(){
return(<p>hi......</p>);
}
}

componentDidMount method not triggered when using inherited ES6 react class

I'm trying to use ES6 classes inside of React, and want all my components to inherit certain methods, however as soon as I try to extend a component which extends the React.Component class, the componentDidMount method doesn't trigger and hence nothing gets rendered. The code I'm using:
BaseComponent.jsx
import React from 'react';
class BaseComponent extends React.Component {
constructor() {
super();
console.log('BaseComponent constructor');
}
render() {
return (
<div>Hello, Im the base component</div>
);
}
}
export default BaseComponent;
ExampleComponent.jsx
import BaseComponent from './BaseComponent';
class ExampleComponent extends BaseComponent {
constructor(props) {
super(props);
}
componentDidMount() {
console.log('exampleComponent mounted');
}
render() {
return (
<div>Hello, Im the example component</div>
);
}
}
export default ExampleComponent;
App.jsx
import React from 'react';
React.render(<ExampleComponent />, document.body);
I'm using React 0.13.3, and using babelify 6.1.2 to transpile.
The string 'exampleComponent mounted' never gets logged to console, and nothing is rendered. Any ideas what I'm doing wrong?
I'm not sure about the approach, but this code also works:
export default class Service extends BaseComponent {
componentDidMount(...args) {
super.componentDidMount.apply(this, args);
}
}
UPD: this is considered to be a bad practice though:
a) https://medium.com/#dan_abramov/how-to-use-classes-and-sleep-at-night-9af8de78ccb4
b) https://medium.com/#dan_abramov/mixins-are-dead-long-live-higher-order-components-94a0d2f9e750
I think, the problem is that you cannot create deeper class-structures for react components. Also, you shouldn't have to need it. On your example the BaseComponent is useless anyway.
Try this instead:
import React from 'react';
export default class ExampleComponent extends React.Component {
constructor(props) {
super(props);
}
componentDidMount() {
console.log('exampleComponent mounted');
}
render() {
return (
<div>Hello, Im the example component</div>
);
}
}
If you want to create 'BaseComponents', you could implement them as mixins or simply as 'sub components'.
This could look like this:
import React from 'react';
import BaseComponent from './BaseComponent';
export default class ExampleComponent extends React.Component {
constructor(props) {
super(props);
}
componentDidMount() {
console.log('exampleComponent mounted');
}
render() {
return (
<div>
<div>Hello, Im the example component</div>
<BaseComponent />
</div>
);
}
}
EDIT: Also possible:
import React from 'react';
import BaseComponent from './BaseComponent';
export default class ExampleComponent extends React.Component {
constructor(props) {
super(props);
}
componentDidMount() {
console.log('exampleComponent mounted');
}
render() {
return (
<BaseComponent
<div>Hello, Im the example component</div>
</BaseComponent>
);
}
}
// BaseComponent.js
render() {
return {
<div>
<div>Hello, Im the base component</div>
{this.props.children}
</div>
}
}
EDIT #2: Above code works fine with es5/jsx syntax.
DEMO

Resources