How to request and receive data from signalR and bind data in ComponentDidMount in ReactJs
I am using react framework to design a view with SignalR. I am able to connect to SignalR server and get data but if I required data to load on view appear I am not able to load data on ComponentDidMount.
If I request data on ComponentDidMount view is displaying blank.
On view load, I mentioned an icon (i) and clicking after view load then the data is binding.
import React, { Component } from 'react';
import { Button, Card, CardBody, CardFooter, CardHeader, Col, Row, Collapse, Fade } from 'reactstrap';
import {Redirect} from 'react-router-dom';
import {hub} from '../../SignalRHub';
class Users extends Component {
constructor(props) {
super(props)
this.state = {
userId:0,
userName:'',
usersList:[]
};
}
LoadUsersList()
{
this.refs.child.userListRequest();
}
receiveUserList(userlist)
{
this.setState({usersList: userlist});
}
render(){
if(this.state.redirecttoUsers)
{
const route='/UsersInfo/'+this.state.userId;
return (<Redirect to={route} />)
}
return (
<form onSubmit={this.handleSubmit}>
<div className="animated fadeIn">
<SignalRHub ref="child" receiveUserList={this.receiveUserList.bind(this)} />
</i>
<Row>
{this.state.usersList.map((e, key) => {
return (
<Col className="col-3 .col-sm-3">
<div class="container">
<Card className="border-primary crd" onClick={(event)=>this.userFingerInfoHandle(event,e)}>
<CardHeader>
{e.userName}
<div className="card-header-actions middle upper">
</i>
<a className="card-header-action img btn btn-setting" onClick={(event)=>this.userRemovalHandle(event,e.id)}><i className="fa fa-trash"></i></a>
</div>
</CardHeader>
<CardBody align="center">
{e.userName}
</CardBody>
</Card>
</div>
</Col>
)})
}
</Row>
</div>
</form>
);
};
}
export default Users;
update state in componentDidMount and reference all necessary data in render using this.state
The reason is simple.
React decide to update the DOM tree when either the props or state is changed by default, so only by changing either of them can you update the rendering unless you implement your own shouldComponentUpdate
Related
This is the same app/continuation of this previous question: Invalid hook call trying to make an axios get request in react
Currently, I'm trying to figure out the best way to conditionally render a component and pass values from my API calls to it. I'll try to explain the current set up of the app the best I can. Here is a link of the non-react version for some visuals: https://giovannimalcolm.github.io/weather-dashboard/
I plan to have a component for the page before any input is submitted. The component I'm working on now is for the current weather box that appears once a city is submitted. I will make a third component for the five forecast cards below the aforementioned.
Currently, in the Home component, I have a onClick on the search button to show the current weather component when clicked. I will probably change this to onSubmit and later add an autocomplete function to the search box for not only more precise results but to also prevent submissions of poor formatting or null submissions. I believe the weather will data will always return with something in this case. The Home component is shown below
import React, { Component } from 'react';
import {Weather} from '../components/TodaysWeather'
import { getWeatherData } from '../service/getWeather';
import { GetWeatherUrl } from '../service/getWeatherUrl';
export class Home extends Component {
constructor(props){
super(props);
this.state = {
location: "",
showWeather: false
};
this.locationChange = this.locationChange.bind(this);
}
onSubmit(e) {
e.preventDefault();
}
locationChange(e){
this.setState({
location: e.target.value
});
}
_showWeather = async (bool) => {
this.setState({
showWeather: bool
});
await getWeatherData(this.state.location)
console.log(await GetWeatherUrl(this.state.location))
}
componentDidUpdate(){
console.log(this.state)
}
render() {
return (
<div>
<header className="main-header">
<h1>Weather Dashboard</h1>
</header>
<div className="container-fluid" style={{ maxWidth: '1400px' }}>
<div className="row">
<aside className="col-lg-3 pb-3">
<h2 id="sidebar-title">Search for a City:</h2>
<form onSubmit={e => this.onSubmit(e)} id="citySearch">
<div className="input-group">
<input
className="form-control"
type="text"
placeholder="City Here"
id="city-input"
onChange={this.locationChange }
/>
<div className="input-group-append"></div>
</div>
<button
type="submit"
className="btn btn-primary btn-block"
id="sidebar-btn"
onClick={this._showWeather.bind(null,true)}
>
Search
</button>
</form>
<div id="history"></div>
</aside>
</div>
</div>
</div>
)
}
}
I have API calls to get the weather data in a separate "service" folder. These are called in the Home component in the _showweather function. What I need help with is figuring out the best way to capture the data from the API call in Home and send it over to the TodaysWeather component (and later the Forecast component) so it can be used for conditionally rendering via states and rendering in the virtual DOM.
I've considered doing the API call in the TodaysWeather component as shown below but this won't work as I need the data to be pulled before any rendering.
import { GetWeatherUrl } from "../service/getWeatherUrl";
import Axios from 'axios';
import React, { Component } from 'react';
export class Weather extends Component {
state = {
loading: true,
weather: []
}
async componentDidMount(){
const res = await Axios.get(GetWeatherUrl());
this.setState({weather: res.data, loading: false})
console.log(this.state.weather);
}
render(){
return(
<div>
<div className="col-lg-9 pb-3">
<section id="presentDay" className="todaysWeather">
<div className="todaysWeather-body">
<h2 className="h3 today-title"> San Diego <img className="weather-img" src="https://openweathermap.org/img/w/03d.png" alt="scattered clouds" /></h2>
<p className="today-txt">Temp: </p>
<p className="today-txt">Wind: 11.5 MPH</p>
<p className="today-txt">Humidity: 61 %</p>
<p>UV Index: <button className="uvi-btn wary-uvi">3.1</button>
</p></div>
</section>
</div>
</div>
)
}
}
Is there a better way to set this all up? Please ignore the strings in the render section, it only was there for debugging.
Hello everyone i installed rsuite through npm i rsuite and imported import "rsuite/dist/styles/rsuite-default.css".
The thing is that buttons or default text inputs works perferctly , but when i use a select or date picker or whatever has to do with a pop up or a collapse they dont show me the data. Like if i click on a select component it does not show me the option even if i can go trhough them and select ! but they are invisible.
Thats my code :
import { Container, Row, Col } from 'reactstrap'
import { DatePicker } from 'rsuite';
import "rsuite/dist/styles/rsuite-default.css"
export default class Forms extends Component {
constructor(props){
super(props)
this.state={
}
}
render() {
return (
<div>
<Container fluid>
<Row className="Col_margin py-4 px-1">
<Col className="Col_margin px-1" md={6}>
<label>name</label>
<DatePicker block/>
</Col>
</Row>
</Container>
</div>
)
}
}```
THATS HOW IT SHOWS TO ME , I CAN CLICK ON IT AND CHOOSE THE DATE BUT I DONT SEE NOTHING, I KINDA CHOSED BLIND
THATS HOW IT SHOULD BE , SHOWING THE DATE OPTIONS AND THE BUTTON OK
I want to tell you that in the first image the date table does not appear visible but is there , like if i move the mouse and click randomly the date appear on the form but it just not show, idk how to show to you because it just not there xD
You just need to import the styling that follows the rsuite package:
import "rsuite/dist/rsuite.min.css";
I would suggest testing your code in a sandbox. I have created codesandbox link. It might be some other possible reason.
import React, { Component } from "react";
import { Container, Row, Col } from "reactstrap";
import { DatePicker } from "rsuite";
import "rsuite/dist/styles/rsuite-default.css";
export default class Forms extends Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
return (
<div>
<Container fluid>
<Row className="Col_margin py-4 px-1">
<Col className="Col_margin px-1" md={6}>
<label>name</label>
<DatePicker block />
</Col>
</Row>
</Container>
</div>
);
}
}
Output:
"The Main class is the container component from where I am importing the Presentational component Menu"
"Regarding dishes.js, DishdetailComponent.js in Main class(where I am importing) these are just used for rendering purpose"
"I just want to know how the onClick() function is communicating with Menu class since there is an onClick()"
"What happens is that there is a list of items displayed on the screen where if an item is clicked the details of it is shown which is handled by another component.. I just want to know what is happening with the onClick() in Menu and the onClick() in Main are they working parallely ? "
import React, { Component } from 'react';
import { Navbar,NavbarBrand } from 'reactstrap';
import Menu from './MenuComponent';
import DishDetail from './DishdetailComponent';
import { DISHES } from '../shared/dishes';
class Main extends Component {
constructor(props){
super(props);
this.state = {
dishes:DISHES,
selectedDish:null
};
}
onDishSelect(dishId){
this.setState({selectedDish:dishId});
}
render(){
return (
<div> {/* class name app has been removed */}
<Navbar dark color="primary">
<div className="container">
<NavbarBrand href="/">Ristorante Con Fusion</NavbarBrand>
</div>
</Navbar>
<Menu dishes={this.state.dishes} onClick={(dishId)=> this.onDishSelect(dishId)}/>
<DishDetail
dish={this.state.dishes.filter((dish) => dish.id === this.state.selectedDish )[0]} />
</div>
);
}
}
</script>
import React, { Component } from 'react';
import { Card, CardImg, CardImgOverlay, CardText, CardBody, CardTitle } from 'reactstrap';
class Menu extends Component {
constructor(props){
super(props);
}
render(){
const menu=this.props.dishes.map( (dish) => {
return(
<div key={dish.id} className="col-12 col-md-5 m-1">
<Card onClick={() => this.props.onClick(dish.id)}>
<CardImg width="100%" src={dish.image} alt={dish.name} />
<CardImgOverlay body className="ml-4">
<CardTitle>{dish.name}</CardTitle>
</CardImgOverlay>
</Card>
</div>
);
}) ;
return(
<div className="container">
<div className="row">
</div>
</div>
);
}
}
export default Menu;
onClick on Menu component rendered in Main component is not an even handler but a prop passed on to the Menu component. For the sake of understand you can think of it like handleClick
The onClick on Card inside Menu is again a prop passed on to the Card component. Since card ccomponent is used from reactstrap, it internally would be rendering a div wherein it would attach an actual onClick handler
Now when the Card is clicked, the handler inside Card is trigger which then calls the onClick passed on as props to it and it further calls this.props.onClick(dish.id) which is the function passed on from Menu component.
The onClicks functions are not executed parallelly but sequentially communication information from child to the parent and further to the grandparent.
The problem is with your naming... It confuses you. The onClick attribute on your Menu is a property passed to your react Menu component. The this.props.onClick receives the function defined in the onClick attribute.
In your menu, the onClick attribute is set on a HTML element so that defines a click handler. It happens that your click handler executes the function in this.props.onClick which has been passed from the parent.
I suggest to change the property name to something more explicit, something like onDishSelection maybe?
I am new to react(started this week). I have a parent and child components and I want to call a parent method in the child component. I have searched through stackoverflow and my code is same as all the solutions I got.
I have a parent component ProductDisplay which displays a list of products:
import React, { Component } from 'react';
import data from '../data'
import Product from '../Product/product.component'
class ProductDisplay extends Component {
constructor(props) {
super(props)
this.state = {
pdts: data,
}
}
addToCart = () => {
console.log('add to cart');
}
render() {
return (
this.state.pdts.map(product => (
<Product
key={product.id}
product={product}
addToCart={this.addToCart}
/>
))
);
}
}
export default ProductDisplay;
and the child component is Product which renders each product
import React, { Component } from 'react';
import { withRouter } from 'react-router-dom';
import "./product.css";
class Product extends Component {
constructor(props) {
super(props);
}
handleClick = () => {
this.props.addToCart();
console.log('click');
}
render() {
const product = this.props.product;
console.log(this.props.addToCart);
return (
<div className="product">
<img className="image" src={product.imgPath} alt={product.name} />
<p className="name">{product.name}</p>
<p className="price">Price: ₹{product.price}</p>
<p className="category">Category: {product.category}</p>
<button className="add">Add To Cart <i className="fa fa-cart-plus"
onClick={this.handleClick}></i></button>
</div>
);
}
}
export default withRouter(Product);
I want to call a function addToCart of ProductDisplay from Product on click of the button but it is not working. The handleClick function of the child omponent itself is not getting called. Hence the parent function which is being called from handleClick is also not getting called.
I’m also not sure if what I am doing would work in binding the method to all the buttons. Please help
You've put the onClick listener on the <i> tag, not on the actual button, which is why its not triggering anything when you click the button.
Try this instead:
<button
className="add"
onClick={this.handleClick}
>
Add To Cart <i className="fa fa-cart-plus"></i>
</button>
You need to bind the addCart method with "this" of the class. And as Chistopher's answer your onClick is on i and not on button.
Either while passing.
<Product
key={product.id}
product={product}
addToCart={this.addToCart}
/>
Or in state
this.addToCart = this.addToCart.bind(this);
I am trying to create a simple SPA (without Router). It has also a simple structure: a component per section:
Home
Services
Products
Product
Modal
Contact us
As you can see the component Products has two sub-components Product and Modal. These are iterated so many times as JSON objects there are:
Products.js
import React, { Component } from "react";
import ReactHtmlParser from "react-html-parser";
import "./Products.css";
import { products } from "./products.json";
import Product from "./Product/Product";
import Modal from "./Modal/Modal";
class Products extends Component {
render() {
return (
<section id='products'>
<div className='container'>
<div className='row'>
{products.map(product => {
return (
<div>
<Product
image={"/img/" + product.image}
name={product.name}
target={product.target}
/>
<Modal
id={product.target}
title={product.name}
body={ReactHtmlParser(product.body)}
/>
</div>
);
})}
</div>
</div>
</section>
);
}
}
export default Products;
Each product has a More Info button what opens the modal and this has another button Budget ("Presupuestar"):
That function should "change the state" of Contact us component (a simple contact us form):
The component has the following code:
Contact.js
import React, { Component } from "react";
import "./Contact.css";
class Contact extends Component {
constructor() {
super();
this.state = { budget: "Contact" };
}
render() {
return (
<section id='contact'>
<div className='container'>
<div className='row'>
<div className='col-xs-12 col-md-6'>
<div className='contact-form'>
<form>
...
{/* Subject */}
<div className='form-group'>
<div className='input-group'>
<span className='input-group-addon' />
<input
type='text'
className='form-control'
id='subject'
aria-describedby='Subject'
placeholder='Subject'
readonly='readonly'
value={this.state.budget}
/>
</div>
{/* /form-group */}
</div>
{/* /Subject */}
...
</form>
</div>
</div>
</div>
</div>
</section>
);
}
}
I guess then I should create a function in the Modal component to trigger with an onClick="setSubject" in the Budget ("Presupuestar") button. What I don't know is how to alter the other component's state.
A quick summary: I have to make the following state update:
I was reading this similar question but I didn't get how to apply in my scenario. Any ideas?
I think you should either but the clickHandler function of the button in the App component that wrap the whole components and then pass it to the Products component then to Modal component but it's not a good practice,
Or you can use Redux a state management system that let you control your state through the whole app.
First of all, you don't need a function to change the state of another component. The smart way to do that is using an intermediary thing to connect 2 component together. There is two way to solve this problem.
The easiest way is you can transfer subject via URL (URL is "the intermediary thing"). When you click the button Presupuestar you can change URL to page contact like this:
/contact?subject=whatever you want
Then, at Contact component, you just need to parse URL to get subject (you can see this question to know how to parse from URL). You can see my example.
The second way is creating a service use singleton pattern to transfer subject from Modal to Contact form. You can see my example.
You can achieve this like this
Create a main app component which will contain all these these three comps
Add a function in app component "changeContacts"
Send it to both the product as well as contacts
Here is an explanation
class App extends Component {
render() {
return (
<div>
<Contact ref="contacts"/>
<Products changeContacts={this.changeContacts} />
</div>
);
}
changeContacts = (newState) => {
this.refs.contacts.changeState(newState)
};
}
class Contact extends Component {
state = { text:"Old Text" }
render() {
return ( <div style={{fontSize:50,backgroundColor:'red'}}>{this.state.text}</div> );
}
changeState = (newState) =>{
this.setState(newState);
}
}
class Modal extends Component {
render() {
return ( <div onClick={() => this.props.onClick({text:"New State Text"})}>This is a modal</div> );
}
}
class Products extends Component {
state = { }
render() {
return ( <div>
<h1>Products List</h1>
<Modal onClick={this.props.changeContacts} />
<Modal onClick={this.props.changeContacts}/>
<Modal onClick={this.props.changeContacts}/>
</div> );
}
}