React Plaid Component Refreshes the page - javascript

Sorry for my English, I'm not a native speaker so please don't minus me too much. I'm a beginner in programming and I'm learning from tutorials found on internet. Today is my first time asking a question on Stack Overflow. It's probably a silly question, I know there are many similar questions, but it's a different issue, it's not a duplicate. Let me move to my question.
I have a react component in which I'm using react-plaid npm package to use Plaid APi. it can be found here react-plaid
My current component code looks like this
Component
import React, {Component} from 'react';
import BuggyApi from "../../services/BuggyApi";
import BlockUi from "react-block-ui";
import ReactPlaid from 'react-plaid'
class Integration extends Component{
state={
plaid_public_key: "",
plaid_public_token: "",
blocking: false,
isSuccess: false,
errorMessage: [],
open: false,
plaidData: [],
};
componentWillMount(){
new BuggyApi().getPlaidPublicKey().then((response)=>{
console.log(response.data);
if(response.status===200){
this.setState({
plaid_public_key: response.data.public_key
});
}
}).catch((error)=>{
})
}
handleOnExit = (error, metadata)=>{
if (error != null) {
console.log('link: user exited');
console.log(error, metadata);
}
};
handleOnLoad =()=>{
console.log('link: loaded');
};
handleOnEvent =(eventname, metadata)=>{
console.log('link: user event', eventname, metadata);
};
handleOnSuccess = (public_token, metadata) => {
console.log('public_token: ' + public_token);
console.log('account ID: ' + metadata.account_id);
};
componentDidMount(){
const script = document.createElement("script");
script.src = "https://cdn.plaid.com/link/v2/stable/link-initialize.js";
script.async = true;
document.body.appendChild(script);
}
render(){
return(
<div className="page-wrapper">
<div className="content container-fluid">
<div className="row">
<div className="col-xs-8">
<h4 className="page-title">Integration</h4>
</div>
<div className="col-xs-4 text-right m-b-30">
</div>
</div>
<div className="row">
<div className="col-md-12">
<div className="text-center">
<h4 className="modal-title">
Link your bank account
</h4>
</div>
<br/>
<br/>
<form>
{(this.state.isSuccess)?
<div className="row">
<div className="col-sm-6 col-sm-offset-3">
<div className="alert alert-success">
<strong>Success!</strong> Settings updated successfully!
</div>
</div>
</div>:null
}
{(this.state.errorMessage.length>0)?
<div className="row">
<div className="col-sm-6 col-sm-offset-3">
<div className="alert alert-danger">
<ul>
{this.state.errorMessage.map((message,i) =><li key={i}>{message}</li>)}
</ul>
</div>
</div>
</div>:null
}
<BlockUi tag="div" blocking={this.state.blocking}>
<div className="row">
<div className="col-sm-6 col-sm-offset-3">
{(this.state.plaid_public_key!=="")?
<div>
<button onClick={() => this.setState({ open: true})}>Open Plaid</button>
<ReactPlaid
clientName="Arshad"
product={["auth"]}
apiKey={this.state.plaid_public_key}
env='sandbox'
open={this.state.open}
onSuccess={(token, metaData) => this.setState({plaidData: metaData})}
onExit={() => this.setState({open: false})}
/>
</div>:null
}
</div>
</div>
</BlockUi>
</form>
</div>
</div>
</div>
</div>
);
};
}
export default Integration;
The problem is when I click the open link button it just shows the Plaid model for few seconds and then refreshes the application page. I'm wondering if someone had the same and can help me out there.
Note:
Please ignore the public key state you can just set it to "c10c40c4ee5eee97764307027f74c2" in apiKey={this.state.plaid_public_key}. I'm getting the public key from the server using axious.

I think I found the issue and though it'd be OK to post my answer on stackoverflow to help others if anyone ever faces the same problem. I was putting the react-plaid-link inside the tags. The react-plaid-link returns a button which according to the html standard a button inside a form without "type" attribute acts like a submit button. Same goes here in my case which I click the the button it submit the form which causes refreshing page. I fixed the issue by just removing the tags. My updated code looks like this.
import React, {Component} from 'react';
import BuggyApi from "../../services/BuggyApi";
import BlockUi from "react-block-ui";
import ReactPlaid from 'react-plaid'
class Integration extends Component{
state={
plaid_public_key: "",
plaid_public_token: "",
blocking: false,
isSuccess: false,
errorMessage: [],
open: false,
plaidData: [],
};
componentWillMount(){
new BuggyApi().getPlaidPublicKey().then((response)=>{
console.log(response.data);
if(response.status===200){
this.setState({
plaid_public_key: response.data.public_key
});
}
}).catch((error)=>{
})
}
handleOnExit = (error, metadata)=>{
if (error != null) {
console.log('link: user exited');
console.log(error, metadata);
}
};
handleOnLoad =()=>{
console.log('link: loaded');
};
handleOnEvent =(eventname, metadata)=>{
console.log('link: user event', eventname, metadata);
};
handleOnSuccess = (public_token, metadata) => {
console.log('public_token: ' + public_token);
console.log('account ID: ' + metadata.account_id);
};
componentDidMount(){
const script = document.createElement("script");
script.src = "https://cdn.plaid.com/link/v2/stable/link-initialize.js";
script.async = true;
document.body.appendChild(script);
}
render(){
return(
<div className="page-wrapper">
<div className="content container-fluid">
<div className="row">
<div className="col-xs-8">
<h4 className="page-title">Integration</h4>
</div>
<div className="col-xs-4 text-right m-b-30">
</div>
</div>
<div className="row">
<div className="col-md-12">
<div className="text-center">
<h4 className="modal-title">
Link your bank account
</h4>
</div>
<br/>
<br/>
{(this.state.isSuccess)?
<div className="row">
<div className="col-sm-6 col-sm-offset-3">
<div className="alert alert-success">
<strong>Success!</strong> Settings updated successfully!
</div>
</div>
</div>:null
}
{(this.state.errorMessage.length>0)?
<div className="row">
<div className="col-sm-6 col-sm-offset-3">
<div className="alert alert-danger">
<ul>
{this.state.errorMessage.map((message,i) =><li key={i}>{message}</li>)}
</ul>
</div>
</div>
</div>:null
}
<BlockUi tag="div" blocking={this.state.blocking}>
<div className="row">
<div className="col-sm-6 col-sm-offset-3">
{(this.state.plaid_public_key!=="")?
<div>
<button onClick={() => this.setState({ open: true})}>Open Plaid</button>
<ReactPlaid
clientName="Arshad"
product={["auth"]}
apiKey={this.state.plaid_public_key}
env='sandbox'
open={this.state.open}
onSuccess={(token, metaData) => this.setState({plaidData: metaData})}
onExit={() => this.setState({open: false})}
/>
</div>:null
}
</div>
</div>
</BlockUi>
</div>
</div>
</div>
</div>
);
};
}
export default Integration;

Sometimes you need to put the Plaid button inside a form element, in which case, just pass (e) => e.preventDefault() in as the onClick handler
<ReactPlaid
clientName="Arshad"
product={["auth"]}
apiKey={this.state.plaid_public_key}
env='sandbox'
open={this.state.open}
onSuccess={(token, metaData) => this.setState({plaidData: metaData})}
onExit={() => this.setState({open: false})}
onClick={(e) => e.preventDefault()}
/>

Related

How to transfer data between two child component in react js?

Actually I'm creating a front-end in which I am taking a mobile number as input on 1st page then after checking mobile number I am moving to OTP page. In OTP page I am taking otp as input and have to send both otp and mobile number to the backend. I am able to pass the otp but dont know how to pass the mobile number as I have taken it as input in the previous page.
Here is Signup Component which will take mobile number input
import React from 'react';
import './Signup.css';
class Signup extends React.Component {
constructor(props){
super(props);
this.state={
mobile:''
}
}
onMobileChange = (event) => {
this.setState({mobile: event.target.value})
}
onSubmitSignup = () => {
fetch('https://cors-anywhere.herokuapp.com/http://8080/signup/checkMobile',{
method:'post',
headers:{'Content-Type':'application/json'},
body: JSON.stringify({
mobile:this.state.mobile
})
})
.then(response => response.json())
.then(data =>{
if(data.content === 'OK'){
this.props.loadNewUser(this.state.mobile);
this.props.onRouteChange('otp','nonav');
}
})
// this.props.onRouteChange('otp','nonav');
}
render(){
const { onRouteChange} = this.props;
return(
<div className='container'>
<div className='mt6'>
<img src={require('./logo.png')} className='logoimg' alt='logo'/>
</div>
<h3 className='text-center b' style={{font:"Montserrat"}}>FOODVIRAAM</h3>
<div>
<article className="br3 ba dark-gray b--white mv4 w-100 w-50-m w-25-l mw6 shadow-6 center">
<main className="pa4 black-80">
<div className="measure">
<fieldset id="sign_up" className="ba b--transparent ph0 mh0">
<div className="mt1">
<label className="db fw5 lh-copy f3" htmlFor="email-address" style={{font:"Montserrat"}}>Enter your mobile number</label>
<input
className="pa2 input-reset ba bg-transparent hover-bg-black bw1 br2 w-100"
type="number"
name="mobile"
id="mobile"
style={{borderColor:"#ffde59",lineHeight:"28px"}}
onChange={this.onMobileChange}
/>
</div>
</fieldset>
<div className="tr">
<input
onClick={this.onSubmitSignup}
className="pv2 input-reset ba b--white bg-transparent grow pointer f3 dib" style={{font:"Montserrat"}} type="submit" value="Send OTP"/>
</div>
</div>
</main>
</article>
</div>
<h5 className="tc mt5" style={{font:"Montserrat"}}>{"#HighwayKaHygienicPitStop"}</h5>
</div>
);
}
}
export default Signup;
OTP component In which I will take OTP as input and then have to send otp and mobile number on Submit
import React from 'react';
import './Signup.css';
class Otp extends React.Component{
constructor(props){
super(props);
this.state={
otp:''
}
}
onOtpChange = (event) => {
this.setState({otp: event.target.value})
}
onSubmitOtp = () => {
console.log(this.props.mobile);
fetch('https://cors-anywhere.herokuapp.com/http://8080/signup/validateOtp',{
method:'post',
headers:{'Content-Type':'application/json'},
body: JSON.stringify({
mobile:this.props.mobile,
otp:this.state.otp
})
})
.then(response => response.json())
.then(data =>{
if(data.content === 'OK'){
// this.props.loadNewUser(this.state.otp);
this.props.onRouteChange('createprofile','nonav');
}
})
this.props.onRouteChange('otp','nonav');
}
render(){
const { mobile,onRouteChange} = this.props;
return(
<div className='container'>
<div className='mt6'>
<img src={require('./logo.png')} className='logoimg' alt='logo'/>
</div>
<h3 className='text-center b' style={{font:"Montserrat"}}>FOODVIRAAM</h3>
<div>
<article className="br3 ba dark-gray b--white mv4 w-100 w-50-m w-25-l mw6 shadow-6 center">
<main className="pa4 black-80">
<div className="measure">
<fieldset id="sign_up" className="ba b--transparent ph0 mh0">
<div className="mt1">
<label className="db fw5 lh-copy f3" htmlFor="email-address" style={{font:"Montserrat"}}>Verify OTP</label>
<input
className="pa2 input-reset ba bg-transparent hover-bg-black bw1 br2 w-100"
type="number"
name="mobile-number"
id="mobile-number"
style={{font:"Montserrat", borderColor:"#ffde59",lineHeight:"28px"}}
onChange={this.onOtpChange}
/>
</div>
</fieldset>
<div className="tr">
<input
onClick={this.onSubmitOtp}
className="pv2 input-reset ba b--white bg-transparent grow pointer f3 dib" style={{font:"Montserrat"}} type="submit" value=""/>
</div>
</div>
</main>
</article>
</div>
<h5 className="tc mt5" style={{font:"Montserrat"}}>{"#HighwayKaHygienicPitStop"}</h5>
</div>
);
}
}
export default Otp;
And this is the parent class
class App extends Component {
constructor(props){
super(props);
this.state={
route:'signup',
route1:'nonav',
newuser:{
mobile:''
}
}
}
loadNewUser = (mobile)=>{
this.setState({user: {
mobile:mobile
}})
console.log(mobile);
}
onRouteChange = (route, route1) =>{
this.setState({route:route});
this.setState({route1:route1});
}
render(){
return (
<div className="App">
{this.state.route1==='nav'
? <div>
<Navigation onRouteChange={this.onRouteChange}/>
{ this.state.route==='editmnc'
? <EditMNC parentMethod={this.onRouteChange}>{this.props.children}</EditMNC>
:<Revenue onRouteChange={this.onRouteChange}/>
}
</div>
}
: <div>
{ this.state.route==='signup'
? <Signup loadNewUser={this.loadNewUser} onRouteChange={this.onRouteChange}/>
: <div>
{ this.state.route==='otp'
? <Otp mobile={this.state.newuser.mobile} onRouteChange={this.onRouteChange}/>
: <div>
{ this.state.route==='createprofile'
? <CreateProfile onRouteChange={this.onRouteChange} />
: <div>
{ this.state.route==='signin'
? <Signin onRouteChange={this.onRouteChange} />
: <AddItem onRouteChange={this.onRouteChange}/>
}
</div>
}
</div>
}
</div>
}
</div>
}
</div>
);
}
}
Use localStorage or Cookies to store your phone number on one page and on the next page, you can easily retrieve the data by whatever medium you choose. Since storing on either of them persist your data, you don't need to worry about an accidental refresh of the page.
Don't use Redux or Context API, as they don't persist the data.
Example :-
Using the localStorage API
// storing the phone number on your first page.
localStorage.setItem('$$NAMESPACE__phone_number', phoneNumber)
// getting the phone number on your second.
const phoneNumber = localStorage.getItem('$$NAMESPACE__phone_number')
Use Redux it's a bit complicated but It is used when you need to transfer data from child to parent,
You can also get the data that you sent by props to child and got a return value
https://redux.js.org

How do I stop the call stack from over loading?

My problem is simple yet infuriating. All I want to do is have an onClick event that when triggered changes the state on the component. The only problem is if I don't stop the addActiveClass function from running initially with the loaded state prop than I get a call stack overload because this component is being rendered by a .map function.
The second I remove the if (this.state.loaded) { //logic } over my state change logic I get
Please help me understand why I can't do this simple thing in React.
class IndividualQA extends Component {
constructor(props) {
super(props);
// this.addActiveClass = this.addActiveClass.bind(this);
this.state = {
active: false,
loaded: false
};
// this.state({ arrowState: this.props.arrowClass });
}
addActiveClass = (load) => {
if (this.state.loaded) {
const currentState = this.state.active;
console.log(this.state);
this.setState({ active: !currentState });
}
};
render() {
return (
<div>
<div className="row">
<div className="col-xl-11 col-lg-11 col-md-11 col-sm-10 col-10">
{this.props.data.Q}
</div>
<div className="col-xl-1 col-lg-1 col-md-1 col-sm-2 col-2 Question">
<a
data-toggle="collapse"
href={`#QA${this.props.id}`}
id="arrowSVG"
onClick={this.addActiveClass()}
>
<img
style={{ height: "30px" }}
className={this.state.active ? "transform" : ""}
src={downArrow}
/>
</a>
</div>
</div>
<div className="row collapse" id={`QA${this.props.id}`}>
<div className="col-xl-11 col-lg-11 col-md-11 col-sm-11 col-11 As-a-long-time-Kiva">
{this.props.data.A}
</div>
</div>
<hr />
</div>
);
}
}
export default IndividualQA;
Your problem is in here
<a
data-toggle="collapse"
href={`#QA${this.props.id}`}
id="arrowSVG"
onClick={this.addActiveClass()} //here
>
This way addActiveClass will be called on every render and can cause a infinty loop.
You need to change it to
<a
data-toggle="collapse"
href={`#QA${this.props.id}`}
id="arrowSVG"
onClick={this.addActiveClass} // without '()'
>
The handler on the a tag should be this.addActiveClass not this.addActiveClass()

React: Update component data/props after promise resolved

I'm a bit new to React and I've been having some problems understanding the workarounds of certain methods that I've used in other languages.
The Problem:
What I was hoping to achieve is that whenever the user clicks a button, the app will render a new section displaying some variable values. What I did was that when the user clicked a button, an state changed, and let the new Component render, and I passed the data through its props.
The problem is, If I understand correctly, that I'm passing the old values when I create the component and not the actual/updated values that I want to render...
Let's say I have this following variables.
const user_data = {
pic_url: 'null',
followers: 'Loading...',
followings: 'Loading...',
nTweets: 'Loading...',
};
Those variables are going to change value whenever the user click a button.
This next block of code is what I use to render the next component where I want the new values.
const SomeComponent = props => {
const [resolved, setResolved] = useState({ display: false });
const displayValidation = props => {
setResolved({ ...resolved, display: !resolved.display });
};
function getData(username) {
const url = 'https://www.twitter.com/' + username;
getHTML(url)
.then(res => {
getUserData(res).then(res => {
user_data.followers = res.followers;
user_data.followings = res.followings;
user_data.nTweets = res.nTweets;
user_data.pic_url = res.pic_url;
console.log('Updated data:', user_data);
displayValidation();
});
})
.catch(function(error) {
console.error('Username was not found.');
});
}
const handleSubmit = event => {
event.preventDefault();
console.log('Resolving data...');
getData(user.username);
};
return (
<React.Fragment>
<Navbar />
<div className="container lg-padding">
<div className="row" id="getTracker">
<div className="col-sm-12 center">
<div className="card text-center hoverable">
<div className="card-body">
<div className="input-field">
<i className="material-icons prefix">account_circle</i>
<input
id="username"
type="text"
className="validate"
value={user.username}
onChange={handleChange}
/>
<label htmlFor="username">Enter a username to track</label>
</div>
<input
type="button"
onClick={handleSubmit}
value="Track"
className="btn-large blue darken-4 waves-effect waves-light"
/>
</div>
</div>
</div>
</div>
<div className="row">
<div className="col-sm-12">
**{resolved.display && <DisplayData type={1} data={user_data} />}**
</div>
</div>
</div>
<Footer />
</React.Fragment>
);
};
I want to see the new values, but it always render the first values that I passed when creating the component.
This is the component that I create
import React from 'react';
const DisplayData = props => {
const user = props.data;
console.log('Display', user);
switch (props.type) {
case 1: //Twitter
return (
<React.Fragment>
<div className="row lg-padding">
<div className="col-sm-12 lg-padding center">
<img
src={user.pic_url}
alt="profile_picture"
style={{ width: 50 + '%' }}
/>
</div>
<h2>{user.username}</h2>
</div>
<div className="row lg-padding">
<div className="col-sm-4">
<h4>Tweets: {user.nTweets}</h4>
</div>
<div className="col-sm-4">
<h4>Followers: {user.followers}</h4>
</div>
<div className="col-sm-4">
<h4>Followings: {user.followings}</h4>
</div>
</div>
</React.Fragment>
);
case 2: //Instagram
return <React.Fragment />;
default:
return (
<React.Fragment>
<div className="row lg-padding">
<div className="col-sm-12 lg-padding center">
<img
src={user.pic_url}
alt="profile_picture"
style={{ width: 50 + '%' }}
/>
<h2>Instagram_User</h2>
<h4>Posts: ND</h4>
<h4>Followers: ND</h4>
<h4>Followings: ND</h4>
</div>
</div>
</React.Fragment>
);
}
};
export default DisplayData;
How can I update the data in the component or render the component when the data is updated?
Maybe your user_data might to be a state object.
// Somecomponent ...
const [user_data, setUser_data] = useState({
pic_url: 'null',
followers: 'Loading...',
followings: 'Loading...',
nTweets: 'Loading...'
})
/* Rest of stuff */
const handleSubmit = async event => {
/*...*/
const userData = await getData(user.username)
setUser_data(userData)
}
// Then display the stated-stored user_data
<div className="col-sm-12">
**{resolved.display && <DisplayData type={1} data={user_data} />}**
</div>

React - Open Modal Dialog (Bootstrap)

First, I'm almost new to reactjs. I want to create a simple editing mask for getting deeper into reactjs.
What is the "Best Practice" for this situation?
I'm having a page, where you can simply add, change or delete a company entry.
What I want to achieve is, to open a modal dialog window, when I click on a company entry. In the modal dialog window then, the user can modify or delete the entry.
First I created a CompanyList component.
import React, { Component } from 'react';
import Company from './Company';
class CompanyList extends Component {
constructor(props) {
super(props);
this.state = {
search: '',
companies: props.companies
};
}
updateSearch(event) {
this.setState({ search: event.target.value.substr(0,20) })
}
addCompany(event) {
event.preventDefault();
let nummer = this.refs.nummer.value;
let bezeichnung = this.refs.bezeichnung.value;
let id = Math.floor((Math.random()*100) + 1);
$.ajax({
type: "POST",
context:this,
dataType: "json",
async: true,
url: "../data/post/json/companies",
data: ({
_token : window.Laravel.csrfToken,
nummer: nummer,
bezeichnung : bezeichnung,
}),
success: function (data) {
id = data.Nummer;
this.setState({
companies: this.state.companies.concat({id, nummer, bezeichnung})
})
this.refs.bezeichnung.value = '';
this.refs.nummer.value = '';
}
});
}
render() {
let filteredCompanies = this.state.companies.filter(
(company) => {
return company.bezeichnung.toLowerCase().indexOf(this.state.search.toLowerCase()) !== -1;
}
);
return (
<div>
<div className="row">
<div className="col-xs-12 col-sm-12 col-md-12 col-lg-12">Search</div>
<div className="col-xs-12 col-sm-12 col-md-9 col-lg-9">
<div className="form-group">
<input className="form-control" type="text" value={this.state.search} placeholder="Search" onChange={this.updateSearch.bind(this)} />
</div>
</div>
</div>
<form onSubmit={this.addCompany.bind(this)}>
<div className="row">
<div className="col-xs-12 col-sm-12 col-md-12 col-lg-12">Create new entry</div>
<div className="col-xs-12 col-sm-12 col-md-3 col-lg-3">
<div className="form-group">
<input className="form-control" type="text" ref="nummer" placeholder="New company no." required />
</div>
</div>
<div className="col-xs-12 col-sm-12 col-md-3 col-lg-3">
<div className="form-group">
<input className="form-control" type="text" ref="bezeichnung" placeholder="New company name" required />
</div>
</div>
<div className="col-xs-12 col-sm-12 col-md-3 col-lg-3">
<div className="form-group">
<button type="submit" className="btn btn-default">Add new company</button>
</div>
</div>
</div>
</form>
<div className="row">
<div className="col-xs-10 col-sm-10 col-md-10 col-lg-10">
<ul>
{
filteredCompanies.map((company)=> {
return (
<div>
<Company company={company} key={company.id} />
</div>
);
})
}
</ul>
</div>
</div>
</div>
);
}
}
export default CompanyList
The Company component looks like this:
import React, { Component } from 'react';
class Company extends Component {
constructor(props) {
super(props);
this.state = {
company: props.company,
onClick: props.onClick
};
}
render() {
return (
<div>
<li>
<div className="cursorPointer" >
{this.props.company.nummer} {this.props.company.bezeichnung}
</div>
</li>
</div>
);
}
}
export default Company
My issue is now, how and where to implement the modal dialog?
Is it best practice to create an own component for it e.g. CompanyOptions? Should it be part of Company or better one component added in CompanyList? But then, how to pass the current Company to the modal dialog.
Sorry, if I'm asking too many questions. But I want to find out how it is recommended in reactjs.
UPDATE
Now I've created an own component for it.
This component looks like this:
import React, { Component } from 'react';
class CompanyOptions extends Component {
constructor(props) {
super(props);
this.state = {
company: props.company,
css: props.css,
onClick: props.onClick
};
}
render() {
return (
<div>
<div className={this.state.css} tabindex="-1" role="dialog">
<div className="modal-dialog" role="document">
<div className="modal-content">
<div className="modal-header">
<button type="button" className="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 className="modal-title">Company entry "{this.state.company.bezeichnung}"</h4>
</div>
<div className="modal-body">
<p>One fine body…</p>
</div>
<div className="modal-footer">
<button type="button" className="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" className="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
</div>
);
}
}
export default CompanyOptions
In the Company component I render it this way:
render() {
return (
<div>
<li>
<div className="cursorPointer" onClick={this.toggleOptionFields.bind(this)}>
{this.props.company.nummer} {this.props.company.bezeichnung}
</div>
<CompanyOptions company={this.state.currentCompany} css={this.state.optionFieldsCss} />
...
I've created a state and a method for the click event:
constructor(props) {
super(props);
this.state = {
company: props.company,
onClick: props.onClick,
editFieldsCss: "displayNone",
optionFieldsCss: "modal fade",
currentCompany: props.company,
};
}
and the method:
toggleOptionFields() {
var css = (this.state.optionFieldsCss === "modal fade in displayBlock") ? "modal fade" : "modal fade in displayBlock";
this.setState({
"optionFieldsCss":css,
currentCompany: this.company
});
}
But when I click on the company the css in the component call is updated. But not in the component itself:
Why? Anybody an idea?
The best way is to create a new component for a modal. This way it would be reusable.
Then you can include it where you need it and you can send all company info via props to that modal.
Add an state property showModal and set it to false. Then onClick event change showModal to true. Then in your render method you can check if(this.state.showModal) and then show modal.
Your state :
constructor(props){
super(props);
this.state = {
showModal: false,
currentCompanyName: "",
currentCompanyNumber: ""
}
}
Then onClick event:
handleClick(currentCompanyName, currentCompanyNumber){
this.setState({
showModal: true,
currentCompanyName: currentCompanyName,
currentCompanyNumber: currentCompanyNumber
})
}
And then in your render:
render(){
if(this.state.showModal)
return <MyModal companyName={this.state.currentCompanyName} companyNumber={this.state.currentCompanyNumber} />
return (
//Rest of the code
)
}

Making two API calls in the same component - reactjs

I'm building an app that produces two tables, each with 5 results. I can't seem to figure out how to crack the code when it comes to mapping over the second table. Table one is {renderItems}, table two is {renderUsers}. The API call for each is at the top of the App.js file detailed below, as 'repoURL' and 'userURL' respectively.
import React, { Component } from 'react';
import axios from 'axios';
const repoURL = 'https://api.github.com/search/repositories?q=stars:>1&s=stars&type=Repositories&per_page=5';
const userURL = 'https://api.github.com/search/users?q=created:>=2016-05-29&type=Users&s=followers&per_page=5';
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
items: []
}
}
componentDidMount() {
var _this = this;
axios.get(repoURL)
.then(function(res){
console.log(res)
_this.setState({
items: res.data.items
});
})
.catch(function(e) {
console.log('ERROR ', e);
})
axios.get(userURL)
.then(function(res){
console.log(res)
_this.setState({
users: res.data.items
});
})
.catch(function(e) {
console.log('ERROR ', e);
})
}
render() {
const renderItems = this.state.items.map(function(item, i) {
return (
<div key={i} className="row">
<div className="col-md-3">{item.id}</div>
<div className="col-md-3">{item.name}</div>
<div className="col-md-3">{item.description}</div>
<div className="col-md-3">{item.stargazers_count}</div>
</div>
);
});
console.log(renderItems)
const renderUsers = this.state.items.map(function(item, i) {
return (
<div key={i} className="row">
<div className="col-md-3">{item.id}</div>
<div className="col-md-3">{item.name}</div>
<div className="col-md-3">{item.description}</div>
<div className="col-md-3">{item.stargazers_count}</div>
</div>
);
});
console.log(renderUsers)
return (
<div className="App">
<div className="row">
<div className="col-md-6 ">
<button type="button" id="hot_repo" className="btn btn-lg btn-danger">Hot Repositories</button>
</div>
<div className="col-md-6 ">
<button type="button" id="prolific_users" className="btn btn-lg btn-success">Prolific Users</button>
</div>
<div id="repoTable" className="col-md-6 panel panel-default">
<div id="repoHeader" className="panel-heading">5 Most Starred Repositories Last Month</div>
<div className="repoSubHeader panel-body">
<div id="repoId" className="col-md-3">ID</div>
<div id="repoName" className="col-md-3">Name</div>
<div id="repoDescription" className="col-md-3">Description</div>
<div id="repoStars" className="col-md-3">Stars</div>
</div>
<div className="row">
{renderItems}
</div>
</div>
<div id="userTable" className="col-md-6 panel panel-default">
<div id="userHeader" className="panel-heading">5 Most Active Users</div>
<div className="userSubHeader panel-body">
<div id="userId" className="col-md-3">ID</div>
<div id="userLogin" className="col-md-3">Login</div>
<div id="userAvatar" className="col-md-3">Avatar</div>
<div id="userFollowers" className="col-md-3">Followers</div>
</div>
<div className="row">
{renderUsers}
</div>
</div>
</div>
</div>
);
}
}
I feel like I'm missing something obvious, but I've been looking at it so long it's not going to be obvious to me at this point. Any help appreciated.
You have to initialize your state in the constructor as:
this.state = {
users: [],
items: []
}
and then you have to map the state items as:
const renderItems = this.state.items.map(function(item, i) {
return (
<div key={i} className="row">
<div className="col-md-3">{item.id}</div>
<div className="col-md-3">{item.name}</div>
<div className="col-md-3">{item.description}</div>
<div className="col-md-3">{item.stargazers_count}</div>
</div>
);
});
const renderUsers = this.state.users.map(function(item, i) {
return (
<div key={i} className="row">
<div className="col-md-3">{item.id}</div>
<div className="col-md-3">{item.name}</div>
<div className="col-md-3">{item.description}</div>
<div className="col-md-3">{item.stargazers_count}</div>
</div>
);
});
console.log(renderUsers)
This is under the assumption that your userUrl returns:
{
items: [
user1,
user2,
...
]
}
If it doesn't, then you need to change this part accordingly.
axios.get(userURL)
.then(function(res){
console.log(res)
_this.setState({
users: res.data.items
});
})
.catch(function(e) {
console.log('ERROR ', e);
})
the first problem I think you are doing a map assigning to const renderUsers a wrong mapping this.state.items.
Secondly you need to declare users key in the this.state in the constructor.
this.setState({ users: [], items: [] })

Categories

Resources