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
)
}
Related
I have two files index.js and map.js. In map.js I have Kartta component, that contains a leaflet map and a method fetchAll() that creates markers on the map from the coordinates that it gets from API, which in this case is test.json. It works fine if I put the method inside componentDidMount(), it creates the markers on load. However I want to create those markers by clicking the button "Haku", which is located inside Sidebar component in index.js.
Here is map.js
import React, { Component } from 'react';
import L from 'leaflet';
import { Map, Marker, Popup, TileLayer } from 'react-leaflet';
import { fetchAll } from './search';
const position = [62.241581, 25.758742];
class Kartta extends Component {
state = {
kohteet: []
}
componentDidMount() {
this.fetchAll();
}
fetchAll = () => {
console.log("täällä");
fetch('test.json')
.then(res => res.json())
.then((data) => {
this.setState({ kohteet: data })
})
.catch(console.log(this.state.kohteet))
}
iconSize = (iconName) => {
if (iconName == 'tree.png') {
return 30, 30
}
else {
return 15, 30
}
}
render() {
return (
<div id="mapid" className="h-100 w-100">
<Map center={position} zoom={7}>
<button onClick={this.haeKaikki}>Hae</button>
<TileLayer
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
attribution="© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors"
/>
{this.state.kohteet.map((kohde) => (
<Marker key={'key' + kohde.id} position={[kohde.lon, kohde.lat]} icon={
new L.Icon({
iconUrl: require('../img/' + kohde.icon),
iconSize: new L.Point(this.iconSize(kohde.icon)),
id: kohde.id + kohde.icon
})
}>
<Popup>
<h1>{kohde.name}</h1>
<p>{kohde.desc}</p>
</Popup>
</Marker>
))}
</Map>
</div>
)
}
}
export default Kartta
Here is index.js
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import './css/main.css';
import 'bootstrap/dist/js/bootstrap.bundle.js';
import 'leaflet/dist/leaflet.css';
import { FontAwesomeIcon } from '#fortawesome/react-fontawesome';
import { faSearch, faInfoCircle } from '#fortawesome/free-solid-svg-icons';
import Kartta from './components/map';
// Yläpalkki
class Navbar extends React.Component {
render() {
return (
<nav id="nav-bar" className="navbar navbar-expand-lg navbar-dark bg-primary">
<a id="nav-bar-a0" className="navbar-brand" href="/">MeijänMetsät</a>
<button id="toggle-search-btn" type="button" href="#sidebar" data-toggle="collapse" className="btn btn-primary">
<FontAwesomeIcon icon={faSearch} />
<span> Haku</span>
</button>
<ul id="nav-bar-ul0" className="navbar-nav mr-auto">
</ul>
<div id="nav-bar-div0" className="dropdown">
<button id="nav-bar-button0" className="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">Kirjaudu
<span id="nav-bar-span0" className="caret"></span></button>
<div id="dropdown-div0" className="p-2 dropdown-menu dropdown-menu-right" style={{"minWidth":"350px"}}>
<form id="dropdown-form0">
<div id="dropdown-div1" className="form-group">
<label id="dropdown-label0" htmlFor="exampleInputEmail1">Sähköposti</label>
<input id="dropdown-input0" type="email" className="form-control" id="exampleInputEmail1" aria-describedby="emailHelp" placeholder="Syötä sähköposti" />
</div>
<div id="dropdown-div2" className="form-group">
<label id="dropdown-label1" htmlFor="exampleInputPassword1">Salasana</label>
<input id="dropdown-input1" type="password" className="form-control" id="exampleInputPassword1" placeholder="Salasana" />
</div>
<div id="dropdown-div3" className="row">
<button id="dropdown-button0" type="submit" className="ml-3 btn btn-primary">Kirjaudu</button>
<button id="dropdown-button2" type="submit" className="ml-2 btn btn-primary">Rekiströidy</button>
<button id="dropdown-button1" type="submit" className="ml-2 btn btn-secondary">Facebook</button>
</div>
</form>
</div>
</div>
</nav>
);
}
}
// Sivupalkki
class Sidebar extends React.Component {
render() {
return (
<div className="p-2 collapse in" id="sidebar">
<div className="list-group panel" id="sidebar-div0">
<form id="sidebar-form0">
<div id="sidebar-div01" className="form-group active">
<label id="sidebar-label0" htmlFor="exampleInputEmail1">Kohteen nimi</label><span> </span>
<FontAwesomeIcon icon={faInfoCircle} className="pointer dropdown-toggle" data-toggle="dropdown" alt="Hakuohjeet" />
<div id="search-info" className="p-2 dropdown-menu dropdown-menu-right">
<p>Hae kirjoittamalla tägejä</p>
</div>
<div className="row">
<div className="col-7 ml-3 p-0">
<input type="text" className="form-control" id="searchByName" aria-describedby="emailHelp" placeholder="Syötä kohteen nimi" />
</div>
<button id="sidebar-button0" type="submit" className="btn btn-primary ml-2 col-3" onClick={() => Kartta.fetchAll}>Haku</button>
</div>
</div>
</form>
<div id="sidebar-div02" className="dropdown">
<a id="sidebar-button1" className="btn btn-light dropdown-toggle p-0 thaku" type="button" data-toggle="dropdown">Tarkennettu haku
<span id="sidebar-span0" className="caret"></span></a>
<div id="sidebar-div020" className="p-0 dropdown-menu border-0 mt-2 w-100 h-100">
<form id="sidebar-form1">
<div id="sidebar-div0200" className="form-group p-0">
<label id="sidebar-label1" htmlFor="exampleInputEmail1">Paikkakunta</label>
<input id="sidebar-input1" type="text" className="form-control" placeholder="Syötä paikkakunta" />
</div>
<div id="ch-div0" className="row pl-3">
<label id="lbl-location">Sijainti</label>
<input id="ch-location" className="mt-2 ml-2" type="checkbox" aria-label="Checkbox for following text input" />
</div>
<div className="input-group mb-3">
<div className="input-group-prepend">
<label className="input-group-text" htmlFor="inputGroupSelect01">Palvelut</label>
</div>
<select className="custom-select" id="inputGroupSelect01">
<option defaultValue>Valitse...</option>
<option value="1">Kakkapaikka</option>
<option value="2">Pissapaikka</option>
<option value="3">Kaljapaikka</option>
</select>
</div>
<div id="dropdown-div3" className="row p-0">
<button id="dropdown-button0" type="submit" className="ml-3 btn btn-primary">Tarkennettu haku</button>
</div>
</form>
</div>
</div>
</div>
</div>
);
}
}
// Sisältö
class Content extends React.Component {
render() {
return (
<div id="main-container" className="container-fluid h-100 p-0">
<Navbar />
<div id="container0" className="row h-100 w-100 m-0 wrapper">
<Sidebar />
<div id="container02" className="col h-100 w-100 p-0">
<Kartta />
</div>
</div>
</div>
);
}
}
ReactDOM.render(<Content />, document.getElementById('root'));
The button "Haku" has onClick={() => Kartta.fetchAll}, but it does not do anything, it isn't even accessing the fetchAll() function. The function works perfectly if I create the button on the map, but I don't want to do that, the button has to be on the Sidebar as the plan is to use a search word in the future.
Thank you!
you need to create a prop e.g. createmap:booleanin Kartta component. Now in index.js firstly you need to create a state e.g. createmap:boolean (initially set to false) and upon Haku button click you need to set the state:
this.setState({
creatmap:true;
});
you need to include Katta component JSX in index.js render() function e.g.
<Kartta createmap = {this.state.createmap} />
Now in Kartta component on componentDidMount()you can check createmap' prop and based on its value call the functionfetchAll()`:
public componentDidMount() {
if(this.prop.createmap) {
fetchAll();
}
}
what this will do is causing rerendering due to setting state upon button click and will call 'fetchAll()' function if createMap is found true
Hope this helps.
EDIT:
Don't forget to use export keyword with your Kartta component class so you can import it in index.js to create its JSX in render():
export default class Kartta extends Component { ... }
EDIT 2
In your navbar component class initialize state in constructor:
export default class NavBar extends Component {
constructor(props) {
super(props);
this.state: {
createmap: false;
}
}
}
your Kartta component class:
export default class Kartta extends Component {
constructor(props) {
super(props);
}
componentDidMount() {
if(this.props.createmap) {
fetchAll();
}
}
I am working on a website where login, register and forgot password popups will appear alternatively (not at a time). So I want to create a modal with multiple body content components.
But I am unable to figure out how to display those. When I click on login or register button Modal content is attaching to modal, but not displaying
Footer.js
import React, { Component } from 'react'
import ModalTemplate from './modals/ModalTemplate'
class Footer extends React.Component {
render() {
return (<><ModalTemplate /></>)
}
}
export default Footer
Footer.js
import React, { Component } from 'react'
import ReactDOM from "react-dom"
import LoginModalBody from './modals/LoginModalBody'
import RegisterModalBody from './modals/RegisterModalBody'
class Header extends Component {
Login() {
ReactDOM.render(<LoginModalBody />, document.getElementById('common_modal_content'));
}
Register() {
ReactDOM.render(<RegisterModalBody />, document.getElementById('common_modal_content'));
}
render() {
return (
<div className='fd bg_Header height_100vh p_5'>
<div className='mainSize'>
<div className="fd">
<div className="row m_0 p_tb_15">
<div className="col-sm-4 col-md-4">
<img className="logoSize" src={Constants.Application.PUB_URL + "/img/logo.svg"} />
<img src={Constants.Application.PUB_URL + "/img/icons/menu.svg"} className="float-right m_r_15 pointer menuIcn"
width="30px" />
</div>
<div className="col-sm-8 col-md-8">
<span className="pointer" onClick={this.Login}>LOGIN
</span> | <span className="pointer" onClick={this.Register}>REGISTER </span>
</div>
</div>
</div>
</div>
)
}
}
export default Header
ModalTemplate.js
import React, { Component } from 'react'
class ModalTemplate extends React.Component {
render() {
return (<> <div id="common_modal" tabindex="-1" role="dialog" class="modal fade">
<div class="modal-dialog">
<div class="modal-content" id="common_modal_content">
</div>
</div>
</div></>);
}
}
export default ModalTemplate;
LoginModalBody .js
import React, { Component } from 'react'
class LoginModalBody extends React.Component {
showModal() {
document.getElementById('common_modal').classList.add('in')
document.getElementById('common_modal').classList.add('show')
}
hideModal() {
document.getElementById('common_modal').classList.remove('in')
document.getElementById('common_modal').classList.add('hide')
}
componentDidMount() {
this.showModal();
}
render() {
return (<>
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Modal Header</h4>
</div>
<div class="modal-body">
<div className="fd">
<h6 className="p_t_15"><b>Log in continue</b></h6>
<input type="text" placeholder="Email address"
className="fd m_t_15 form-control bck_ligrey bdr_0" />
<input type="text" placeholder="Password"
className="fd m_t_15 form-control bck_ligrey bdr_0 brdr_grey" />
<div className="fd m_t_15">
<input type="checkbox" />
<font color="#ddd">Remember My password</font>
<p className="float-right font-12 m_0">Show password</p>
</div>
<button type="button" className="btn fd btn_orng font-12 m_tb_10"> Log in</button>
<div className="fd p_b_15 text-center">
<u><b>Forgot password?</b></u>
</div>
<p className="fd m_b_10 m_t_30 text-center"><span className="font-10">Don't have an account?</span> <b>Sign Up</b></p>
</div>
</div>
</>
);
}
}
export default LoginModalBody;
Add your modal component in separate file and import that in Footer or Header.
const [content, setContent] = useState(); State for your content.
You need to create a function that will define which modal content you want to display. You can pass type as follows: `onClick={() => callModalComponent('login')}
Your function will be like:
const callModalComponent = (type: string) => {
if(type === 'login'){
setContent(<LoginComponent />) // set state content as per your form requirement
} else if(type === 'register'){
setContent(<RegisterComponent />)
}
openModalContainer() // this will open your modal.
}
I create a component of react. and there one array with some values. so I need to display that value or data in any specific div by clicking in a button.
this is my array in component.
constructor(){
super()
this.state = {
notificaion: [
"Notification-1",
"Notification-3",
"Notification-4",
"Notification-5",
]
}
}
this is my button with click event.
<button onClick={this.getNotification}>{this.state.notificaion.length}</button>
this is the function that I have create. and to push data in specific div.
getNotification = () =>{
return(
this.state.notificaion.map(items =>(
<li key={items}>{items}</li>
))
)
}
here I want to display when buttons is clicked
<strong>{this.getNotification()}</strong>
This is my full code that I have been tried.
import React, {Component} from 'react';
class Menu2 extends Component{
constructor(){
super()
this.state = {
notificaion: [
"Notification-1",
"Notification-3",
"Notification-4",
"Notification-5",
]
}
}
getNotification = () =>{
return(
this.state.notificaion.map(items =>(
<li key={items}>{items}</li>
))
)
}
render(){
return(
<div className="header">
<div className="container">
<div className="row">
<div className="col-lg-12 col-sm-12 col-xs-12">
<div className="text-center mb-20">
<h1>Notificaion Status</h1>
<p>Check notificatin read/unread</p>
</div>
</div>
</div>
<div className="row">
<div className="col-lg-12 col-sm-12 col-xs-12">
<div className="card border-dark mb-3">
<div className="card-body text-dark">
<p className="card-text" style={{textAlign: 'center'}}>
{this.state.notificaion.length > 0
?
<span>You Have <button onClick={this.getNotification}>{this.state.notificaion.length}</button> Unread Notifications</span>
:
<span>You Have <button onClick={this.getNotification}>{this.state.notificaion.length}</button> Unread Notifications}</span>}
</p>
<strong>{this.getNotification()}</strong>
</div>
</div>
</div>
</div>
</div>
</div>
);
}
}
export default Menu2;
import React, { Component } from 'react';
class App extends Component {
constructor(props) {
super(props);
this.state = {
notificaion: [
"Notification-1",
"Notification-3",
"Notification-4",
"Notification-5",
],
notificationHtml: ""
}
}
getNotification = () => {
this.setState({
notificationHtml: this.state.notificaion.map(items => (
<li key={items}>{items}</li>
))
});
}
render() {
return (
<div className="App">
<button onClick={this.getNotification}>{this.state.notificaion.length}</button>
<div>
{this.state.notificationHtml}
</div>
</div>
);
}
}
export default App;
I would implemented as such:
this.state = {
visible: false,
notifications: ...
}
toggleVisibility() =>{
this.setState({
visibile: true
})
}
Don't forget to bind the "toggleVisibility" function. Then
in your component:
<button onClick={this.toggleVisibility}/>
...
{if(this.state.visible){
<strong>this.state.notifications.map(notification,i) =>
<li key={i}>{notification}</li>
</strong>
}
You can add a property showNotification in state. And based on the value of it, we can show the notification.
Also add a method showNotificationHandler that toggles the showNotification value.
class Menu2 extends Component {
constructor() {
super();
this.state = {
notificaion: [
"Notification-1",
"Notification-3",
"Notification-4",
"Notification-5"
],
// adding a property "showNotification"
showNotification: false
};
}
getNotification = () => {
return this.state.notificaion.map(items => <li key={items}>{items}</li>);
};
// method that toggles the "showNotification" value
showNotificationHandler = () => {
this.setState(({ showNotification }) => ({
showNotification: !showNotification
}));
};
render() {
return (
<div className="header">
<div className="container">
<div className="row">
<div className="col-lg-12 col-sm-12 col-xs-12">
<div className="text-center mb-20">
<h1>Notificaion Status</h1>
<p>Check notificatin read/unread</p>
</div>
</div>
</div>
<div className="row">
<div className="col-lg-12 col-sm-12 col-xs-12">
<div className="card border-dark mb-3">
<div className="card-body text-dark">
<p className="card-text" style={{ textAlign: "center" }}>
{this.state.notificaion.length > 0 ? (
<span>
You Have{" "}
<button onClick={this.showNotificationHandler}>
{this.state.notificaion.length}
</button>{" "}
Unread Notifications
</span>
) : (
<span>
You Have{" "}
<button onClick={this.showNotificationHandler}>
{this.state.notificaion.length}
</button>{" "}
Unread Notifications}
</span>
)}
</p>
<strong>
// Depending on the value of "showNotification" we get notification
// if "showNotification" is true then get the notification
{this.state.showNotification && this.getNotification()}
</strong>
</div>
</div>
</div>
</div>
</div>
</div>
);
}
}
export default Menu2;
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()}
/>
import React from 'react';
import 'materialize-css/sass/materialize.scss';
import 'materialize-css/js/materialize.js';
import 'font-awesome/scss/font-awesome.scss';
import '../styles/main.scss';
export default class AddStorageModal extends React.Component {
constructor() {
super();
this.state = { storageName: "", sharingKey: "" };
}
handleChange(event) {
this.setState({ [event.target.name]: event.target.value });
}
validate() {
if (this.state.storageName === "" && this.state.sharingKey == "") {
console.log("validation error");
return false;
}
this.props.createNewStorage(this.state);
}
resetForm() {
this.setState({ storageName: "", sharingKey: "" });
$(function () {
Materialize.updateTextFields();
});
}
render() {
if (this.props.storages.openAddStorageModal) {
$('#add-new-storage-modal').openModal({ dismissible: false });
}
else {
this.resetForm.bind(this);
$('#add-new-storage-modal').closeModal();
}
return (
<div id="add-new-storage-modal" className="modal" >
<div className="modal-content">
<h6>Enter your new Storage (Freezer, Pantry, etc.) </h6>
<div className="row">
<form>
<div className="input-field col s12 m12 l12 ">
<input id="storage_name" type="text" value={this.state.storageName} name="storageName" onChange={ (event) => this.handleChange(event) } />
<label htmlFor="storage_name">Storage Name</label>
</div>
<br />
<h4 className="center">OR</h4>
<h6>Enter in the sharing key you were given.</h6>
<div className="input-field col s12 m12 l12 ">
<input id="sharing_key" type="text" value={this.state.sharingKey} name="sharingKey" onChange={ (event) => this.handleChange(event) } />
<label htmlFor="sharing_key">Sharking Key</label>
</div>
</form>
</div>
</div>
<div className="modal-footer">
<a href="#!" className="waves-effect waves-green btn-flat left" onClick={() => this.validate() }>Add</a>
<a href="#!" className="waves-effect waves-green btn-flat" onClick={() => this.props.loadAddStorageModal(false) }>Cancel</a>
</div>
</div>
)
}
}
When "this.resetForm.bind(this);" gets hit, it does not execute it. It use to work but I don't know what I did but now it does not work.
I going to have to work backwards and remove what I did to see if I can figure it out but hoping someone might just know why.
That line doesn't do anything anyway. Function.prototype.bind returns a new function, but you're not doing anything with the returned function.
You'll have to be more clear about what you expect that line to do to get a better answer than this. Maybe you just meant to call resetForm like this:
this.resetForm( );