import React, { Component } from 'react';
let _ = require('lodash');
import {bindActionCreators} from "redux";
import {connect} from 'react-redux';
import {fetchedZonesEdit} from '../../actions/';
class InfoRow extends Component {
constructor(props){
super(props);
this.handleInputChange = this.handleInputChange.bind(this);
}
handleInputChange(event) {
this.setState({
[event.target.name]: event.target.value
});
}
render() {
return (
<tr>
<td>
{this.props.zone}
</td>
<td>{this.props.zoneValue}
<input type="text"
className="form-control"
defaultValue={this.props.zoneValue}
value={this.props.name}
name={this.props.zone}
onChange={this.handleInputChange}
/>
</td>
</tr>
)
}
}
class ZoneDetailsEdit extends Component {
render() {
const rows = [];
let a = this.props.ezn;
Object.keys(this.props.ezn).map((keyName, keyIndex) =>{
return rows.push(<InfoRow zone={keyName} zoneValue={a[keyName].toString()} key={keyIndex}/>)
});
return (
<div className="col-md-6">
<div className="">
<table className="table table-clear">
<tbody>
{rows}
</tbody>
</table>
</div>
<div className="row px-1" >
<div className="px-2">
<button className="btn btn-sm btn-info">Save</button>
</div></div>
</div>
)
}
}
class ZoneDetailEditComponent extends Component {
componentWillMount = () => {
this.props.fetchedZonesEdit(this.props.location.query.id);
};
render() {
return (
<div className="container px-3 mr-3">
<div className="row">
<div className="col-md-6 col-md-offset-3"><h1>Edit Tag Information</h1></div>
</div>
<br/>
<br/>
{ this.props.ezn != null?
<div>
<ZoneDetailsEdit ezn={this.props.ezn}/>
</div> :
<center><br /><h1><img src={'img/avatars/default.gif'} alt="Loading"/><br />Loading</h1></center>
}
</div>
)
}
}
function mapStateToProps(state) {
return {
ezn: state.zones
}
}
function matchDispatchToProps(dispatch){
return bindActionCreators({fetchedZonesEdit: fetchedZonesEdit}, dispatch);
}
export default connect(mapStateToProps, matchDispatchToProps)(ZoneDetailEditComponent);
This is the snippet i provided
what I'm doing right now is i had fetched the data from the api and was shown in the input fields but the issue is data is fetched correctly but when i print outside input fields it works fine but when i enter in input fields as default value it doesn't works
screenshot also provided
when opened the page default values are set of previous page but when it is refreshed it works fine
defaultValue should be used only on Uncontrolled components.
Instead of using defaultValue, assign a default value to the name in your store.
Also, don't use this.setState if you are using redux. You are assigning the new value to this.state.zone which you never read.
Since you are using a controlled component you need not use defaultValue, assigning the props passed down to the value will suffice.
Also using redux, a better practice is to store the UI state in localState and all others in the redux store.
To do that you need to dispatch an action that updates the corresponsing reducer after passing the values to the topmost parent
Also you are not passing any prop as name to the InfoRow component and since defaultValue is rendered only at the time of create, you do not see the update.
You code must look something like
import React, { Component } from 'react';
let _ = require('lodash');
import {bindActionCreators} from "redux";
import {connect} from 'react-redux';
import {fetchedZonesEdit} from '../../actions/';
class InfoRow extends Component {
constructor(props){
super(props);
this.handleInputChange = this.handleInputChange.bind(this);
}
handleInputChange(event) {
this.props.handleChange(this.props.zone, event.target.value);
}
render() {
return (
<tr>
<td>
{this.props.zone}
</td>
<td>{this.props.zoneValue}
<input type="text"
className="form-control"
value={this.props.zoneValue}
name={this.props.zone}
onChange={this.handleInputChange}
/>
</td>
</tr>
)
}
}
class ZoneDetailsEdit extends Component {
handleChange(zone, value) {
//pass it to the parent and then fire an action from there to update this value in the store
}
render() {
const rows = [];
let a = this.props.ezn;
Object.keys(this.props.ezn).map((keyName, keyIndex) =>{
return rows.push(<InfoRow zone={keyName} zoneValue={a[keyName].toString()} handleChange={()=> this.handleChange}key={keyIndex}/>)
});
return (
<div className="col-md-6">
<div className="">
<table className="table table-clear">
<tbody>
{rows}
</tbody>
</table>
</div>
<div className="row px-1" >
<div className="px-2">
<button className="btn btn-sm btn-info">Save</button>
</div></div>
</div>
)
}
}
Also there is no need for you to bind the lifeCycle function with arrows
Related
I am new to react and I am having difficulty receiving value from another component. So what I am trying to do is that I am taking in an input value which is the stock ticker from the user in serachBar.js and passing the the ticker value to salesModel.js where the stock data will be displayed in a table format. However, before displaying the data I am sending the value to StockData.js where the API retrives the information based on the user input and sends the data back to the salesModel.js file to be displayed. However, for reason I cant pass the value from the searchBar.js file tosalesModel.jsfile. I have places the code the below for both components and also thank you in advance for any advice I would really appreciate it.
Searchbar.js
class SearchBar extends React.Component{
constructor(props){
super(props);
this.state = {
inputTicker:''
}
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
// handleSubmit (event) {
handleSubmit = event => {
event.preventDefault();
const { inputTicker } = this.state;
console.log("Current value?", inputTicker);
}
handleChange = event => {
// handleChange(event) {
// event.preventDefault();
console.log("Taking in value:",event.target.value);
this.setState({
inputTicker: event.target.value
});
// console.log("State:", JSON.parse(this.state.inputTicker));
}
render() {
return(
<div>
<form onSubmit={this.handleSubmit} >
<div className="search-container">
<span className="search-icon-btn" >
<button className="search-icon-btn"
value="Submit"
type="submit"
>
<i className="fa fa-search" ></i>
</button>
</span>
<div className="search-input">
<input
type="text"
className="search-bar"
placeholder="Search ticker symbol..."
value={this.state.inputTicker}
onChange= {this.handleChange}
/>
</div>
</div>
</form>
</div>
)
}
}
export default SearchBar;
salesModel.js
class salesModel extends Component{
// function salesModel (props) {
constructor(props){
super(props);
this.state = {
ticker:''
}
}
componentDidMount() {
console.log("passed the value:",this.props.inputTicker);
}
render(){
return(
<div className="salesModel" >
<h1>Price to Sales Model (PS)</h1>
<table className="table mt-5">
<tbody>
<tr>
<th>Ticker</th>
<th>Company</th>
<th>Price</th>
<th>PE Ratio</th>
<th>Market Cap</th>
<th>Shares Outstanding</th>
<th>Beta</th>
</tr>
</tbody>
<tbody>
{/* <SearchBar handleSubmit={(input)=> this.setState({ticker: input})}/> */}
{/* <StockData ticker = "AAPL" /> */}
{/* <StockData ticker = {this.props.inputTicker} /> */}
</tbody>
</table>
</div>
);
}
}
export default salesModel;
I have tried calling the <SearchBar handleSubmit={(input)=> this.setState({ticker: input})}/> and setting the value as to ticker but for some reason that didn't work as well. I have tried to use the props.inputTicker from the searchBar.js file but for some reason it would give me an error Uncaught (in promise) SyntaxError: Unexpected token U in JSON at position 0. Honestly I have been stuck at this problem for sometime any help would be greatly appreciative thank you.
So what you need is a parent component that takes care of the state for both of them.
In this example the App.js is the parent and the SearchBar.jsand SalesModal.js are the children
Here is an codesandbox example
// App.js (parent component)
import React, { useState } from "react";
import SearchBar from "./SearchBar";
import SalesModal from "./SalesModal";
const App = () => {
const [searchBarText, setSearchBarText] = useState("");
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<SearchBar
searchBarText={searchBarText}
setSearchBarText={setSearchBarText}
/>
<SalesModal searchBarText={searchBarText} />
</div>
);
};
export default App;
// SearchBar.js (child component)
import React from "react";
const SearchBar = ({ searchBarText, setSearchBarText }) => {
return (
<input
type="text"
value={searchBarText}
onChange={(e) => setSearchBarText(e.target.value)}
/>
);
};
export default SearchBar;
// SalesModal.js (child component)
import React from "react";
const SalesModal = ({ searchBarText }) => {
return <div> searchBar Text: {searchBarText}</div>;
};
export default SalesModal;
I've come to a halt making this covid19 app where I can see a list of countries on the left side of the screen with the option of adding any number of countries to the right side of the screen, which displays more covid data of the added country. I'm also kinda new to React.
Problem is, when I click the add button the added state is updated, and it displays that added country on the right side of the screen. But, when I try adding another country I get an error. I believe the error is somewhere around when I try to setState({ state }) in the addCountry method from within App.js.
In other words, the 'added' state is only letting itself hold no more than one array element. Help much much much appreciated. I posted all the code.
index.js
import ReactDOM from 'react-dom';
import 'bootstrap/dist/css/bootstrap.min.css';
import './index.css';
import App from './App';
ReactDOM.render(<App />, document.getElementById('root'));
App.js
import CountryList from "./components/CountryList.js";
import Find from "./components/Find.js";
import Added from "./components/Added.js";
class App extends Component {
constructor() {
super();
this.state = {
countries: [],
inputbox: [],
added: [],
};
}
// Arrow functions capture "this" when they are defined, while standard functions do when they are executed.
// Thus, no need for the bind method. Awesome.
handleChange = (e) =>
this.setState({
inputbox: e.target.value,
});
getCountryData = async (slug) => {
const resp = await fetch(`https://api.covid19api.com/live/country/${slug}`);
var addedData = await resp.json();
// Api returns most days of covid, per country, that it tracks
// Thus, we want the last tracked day of a country
addedData = addedData[addedData.length - 1];
return addedData;
};
// Add a country to the added state
// Call when user clicks button associated with their desired country
addCountry = async (btnId) => {
const { countries, added } = this.state;
var addedData = await this.getCountryData(btnId);
countries.map((country) => {
// If the button ID is equal to the current country in the loops' Slug
if (btnId == country.Slug) {
try {
added.push([
{
addedCountry: addedData.Country,
confirmedTotal: addedData.Confirmed,
deathsTotal: addedData.Deaths,
recoveredTotal: addedData.Recovered,
activeTotal: addedData.Active,
},
]);
// (bug) IT IS PUSHING, BUT ITS NOT SETTING THE STATE!
// ITS ONLY LETTING ME KEEP ONE ITEM IN THE STATE
this.setState({ added });
console.log(added);
} catch (error) {
alert(`Sorry, country data not available for ${country.Country}`);
return;
}
}
});
};
removeCountry = (btnId) => {
const { added } = this.state;
added.map((added, index) => {
//console.log(added[index].addedCountry);
if (btnId == added[index].addedCountry) {
added.splice(index, 1);
this.setState({ added: added });
} else {
console.log("not removed");
return;
}
});
};
// Mount-on lifecycle method
async componentDidMount() {
const resp = await fetch("https://api.covid19api.com/countries");
const countries = await resp.json(); // parsed response
this.setState({ countries }); // set state to parsed response
}
render() {
// Filter out countries depending on what state the inputbox is in
const { countries, inputbox } = this.state;
const filtered = countries.filter((country) =>
country.Country.includes(inputbox)
);
return (
<div className="App Container">
<Find
placeholder="Type to find a country of interest..."
handleChange={this.handleChange}
/>
<div className="row">
<CountryList countries={filtered} addCountry={this.addCountry} />
<Added added={this.state.added} removeCountry={this.removeCountry} />
</div>
</div>
);
}
}
export default App;
Added.js
import React, { Component } from "react";
import { Table, Form, Input, Button } from "reactstrap";
import AddedCountry from "./AddedCountry.js";
class Added extends Component {
constructor(props) {
super(props);
}
render() {
return (
<div className="col-md-6">
<Table>
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Country</th>
<th scope="col">Active</th>
<th scope="col">Confirmed Total</th>
<th scope="col">Recovered</th>
<th scope="col">Deaths</th>
<th scope="col">Action</th>
</tr>
</thead>
{this.props.added.map((added, index) => (
<AddedCountry
added={added[index]}
removeCountry={this.props.removeCountry}
/>
))}
</Table>
</div>
);
}
}
export default Added;
AddedCountry.js
import React, { Component } from "react";
import { Table, Form, Input, Button } from "reactstrap";
class AddedCountry extends Component {
constructor(props) {
super(props);
}
render() {
return (
<tbody>
<tr>
<td></td>
<td>{this.props.added.addedCountry}</td>
<td>{this.props.added.activeTotal}</td>
<td>{this.props.added.confirmedTotal}</td>
<td>{this.props.added.recoveredTotal}</td>
<td>{this.props.added.deathsTotal}</td>
<td>
{
<Button
onClick={() =>
this.props.removeCountry(
document.getElementById(this.props.added.addedCountry).id
)
}
id={this.props.added.addedCountry}
type="submit"
color="danger"
size="sm"
>
Remove
</Button>
}
</td>
</tr>
</tbody>
);
}
}
export default AddedCountry;
CountryList.js
import React, { Component } from "react";
import { Table, Form, Input, Button } from "reactstrap";
import Country from "./Country.js";
class CountryList extends Component {
constructor(props) {
super(props);
}
render() {
return (
<div className="col-md-6">
<Table>
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Country</th>
<th scope="col">Actions</th>
</tr>
</thead>
{
// Each country is a component
// Function will display all countries as the Map function loops through them
this.props.countries.map((country) => (
<Country countries={country} addCountry={this.props.addCountry} />
))
}
</Table>
</div>
);
}
}
export default CountryList;
Country.js
import React, { Component } from "react";
import { Table, Form, Input, Button } from "reactstrap";
class Country extends Component {
constructor(props) {
super(props);
}
render() {
return (
<tbody>
<tr>
<td></td>
<td>{this.props.countries.Country}</td>
<td>
{
<Button
onClick={() =>
this.props.addCountry(
document.getElementById(this.props.countries.Slug).id
)
}
id={this.props.countries.Slug}
type="submit"
color="success"
size="sm"
>
Add
</Button>
}
</td>
</tr>
</tbody>
);
}
}
export default Country;
Find.js
import React, { Component } from "react";
import { Table, Form, Input, Button } from "reactstrap";
class Find extends Component {
constructor(props) {
super(props);
}
render() {
return (
<div className="Find container">
<br />
<Form>
<div className="form-row">
<div className="form-group col-md-6">
<h3>Find a Country</h3>
<Input
type="text"
className="form-control"
id="country"
placeholder={this.props.placeholder}
onChange={this.props.handleChange}
></Input>
</div>
</div>
</Form>
</div>
);
}
}
export default Find;
I haven't pored over all that code, but focusing right where you think the issue is it is obvious you are mutating your state object by pushing directly into the added array.
Solution
Don't mutate state!
Since it seems you only want to add a single new "add" and only when the button's btnId matches a country's slug, and the btnId can only ever be a valid value from the mapped countries array, I think this can be greatly simplified.
addCountry = async (btnId) => {
const addedData = await this.getCountryData(btnId);
if (addedData) {
this.setState(prevState => ({
added: prevState.added.concat({ // <-- concat creates a new array reference
addedCountry: addedData.Country,
confirmedTotal: addedData.Confirmed,
deathsTotal: addedData.Deaths,
recoveredTotal: addedData.Recovered,
activeTotal: addedData.Active,
}),
}));
} else {
alert(`Sorry, country data not available for ${country.Country}`);
}
};
Similarly the removeCountry handler is mis-using the array mapping function and mutating the added state. Array.prototype.filter is the idiomatic way to remove an element from an array and return the new array reference.
removeCountry = (btnId) => {
this.setState(prevState => ({
added: prevState.added.filter(el => el.addedCountry !== btnId),
}));
};
Additional Issues & Suggestions
Added.js
If you maintain the added array as a flat array (not an array of arrays) then it's trivial to map the values.
{this.props.added.map((added) => (
<AddedCountry
key={added}
added={added}
removeCountry={this.props.removeCountry}
/>
))}
Country.js & AddedCountry.js
I don't see any reason to query the DOM for the button id when you are literally right there and can enclose the country slug in the onClick callback.
<Button
onClick={() => this.props.addCountry(this.props.countries.Slug)}
id={this.props.countries.Slug}
type="submit"
color="success"
size="sm"
>
Add
</Button>
<Button
onClick={() => this.props.removeCountry(this.props.added.addedCountry)}
id={this.props.added.addedCountry}
type="submit"
color="danger"
size="sm"
>
Remove
</Button>
App.js
This may or may not matter, but it is often the case to do case-insensitive search/filtering of data. This is to ensure something like "France" still matching a user's search input of "france".
const filtered = countries.filter((country) =>
country.Country.toLowerCase().includes(inputbox.toLowerCase())
);
I want to use two props in the grap_test component, one prop comes from a test.js component and the other comes from App.js. I have made a attempt where in graph_test.js i call them and use them in a temporary example to see if they are getting passed through.
However it says:
TypeError: Cannot read property 'map' of undefined
on the 17 line of graph_test.
Does annybody have any suggestions?
Graph_Test:
import React from 'react';
import $ from "jquery";
//<h1>{props.testing.map}</h1>
const Graph_Test = props => {
return(
<div>
<div>
{props.testing.map((item, idx) => {
return (
<label key={idx}>
<input className="region" type="radio" value={idx} />
<span>{idx}</span>
</label>
);
})}
</div><div>
<h1>{props.array[0]}</h1>
</div>
</div>
);
};export default Graph_Test;
Test
import React from 'react';
import $ from "jquery";
import Graph_Test from "./Graph_Test.js";
const Test = props => {
const total_regions = (JSON.parse(JSON.stringify(props.test)).length); // gets the number of regions
var ROI = [];
for (var i = 0; i < total_regions.length; i++) { // Array to represent which regions need to be displayed
ROI[i] = 0; // deault setting all regions equal 1 as must be displayed
}
//when a radio button is clicked change its corresponding in the array
const handleClick = (item, idx) => {
if(ROI[idx] == 1){ // if region displayed and clicked -> undisplay region
ROI[idx] = 0;
}else{ // if region not displayed and clicked -> display region
ROI[idx] = 1;
}
console.log(`Array ${ROI[idx]} with index ${idx} clicked`); // Used to test functionality of array
};
return (
// displays radio buttons depending on the number of objects in json
<div>
<div>
{props.test.map((item, idx) => {
return (
<label key={idx}>
<input className="region" type="radio" value={idx} onClick={() => handleClick(item, idx)}/>
<span>{idx}</span>
</label>
);
})}
</div>
<div>
<Graph_Test array = {ROI}/>
</div>
</div>
);
};
export default Test;
App.js
import "bootstrap/dist/css/bootstrap.css";
import React from "react";
import ReactPlayer from 'react-player'
import LeftPane from "./components/LeftPane.js";
import Video from "./components/Video.js";
//import Footer from "./components/Footer.js";
import Test from "./components/Test.js";
import Graph_Test from "./components/Graph_Test.js";
//import './App.css';
class App extends React.Component {
constructor(props) {
super(props);
this.state = { apiResponse: [] };
}
// Comunicate with API
callAPI() {
fetch("http://localhost:9000/IntensityAPI") //React app talks to API at this url
.then(res => res.json())
.then(res => this.setState({ apiResponse: res }));
}
componentWillMount() {
this.callAPI();
}
render() {
return (
<div className="App">
<div class="row fixed-top fixed-bottom no-gutters" >
<div class="col-3 fixed-top fixed-bottom">
<LeftPane></LeftPane>
</div>
<div class="offset-md-3 fixed-top fixed-bottom" >
<Video></Video>
</div>
<div class=" col-3 fixed-bottom">
<Graph_Test testing = {this.state.apiResponse}/>
<Test test = {this.state.apiResponse}/>
</div>
</div>
</div>
);
}
}
export default App;
The main problem here is in function component you don't have this. You were trying to use with this.props.testing.map(). Try to remove this which most probably solves the issue.
Instead try as the following:
return <div>
{props.testing && props.testing.map((item, idx) => {
return (
<label key={idx}>
<input className="region" type="radio" value={idx} />
<span>{idx}</span>
</label>
);
})}
</div><div>
<h1>{props.array[0]}</h1>
</div>
+1 suggestion after question has been updated:
I have extended my solution for null or undefined checks with &&. If you add props.testing && props.testing.map() then you won't have the error what you face in the second problem.
Also one good solution is you need to pass testing as well once you use the component:
<Graph_Test array={ROI} testing={[]} /> { /* passing testing with [] */ }
Or passing array with []:
<Graph_Test testing={this.state.apiResponse} array={[]} />
You need to have both props with default values or checking for undefined or null values in the <Graph_Test /> component.
I hope this helps!
In your first file, you reference this.props, but 'this' doesn't exit in a functional component. Just remove it
I cannot get the component displayed to update when the index increases. I am able to console the proper component now but because the onClick is below the component that needs to update, it isn't changing. Can someone help me fix my code? i think I am close but cannot figure it out for the life of me.
This sign up page is where I would like to update the component. Essentially I want to display each component in the array once the next button is clicked. Currently the function console logs everything as I want it to, it's just a matter of getting it to appear in the
it is returning an error "cannot read property 'count' of null":
import React from 'react';
import Q1Name from './questions/Q1Name';
import Q2Birthday from './questions/Q2Birthday';
import Q3City from './questions/Q3City';
import Q4YouReady from './questions/Q4YouReady';
import Q5Setting from './questions/Q5Setting';
import Q6Length from './questions/Q6Length';
import Q7Email from './questions/Q7Email';
class SignUpPage extends React.Component {
constructor(props) {
super(props);
this.state = {
i: 0
}
}
_handleClick() {
const components = [Q1Name, Q2Birthday, Q3City, Q4YouReady, Q5Setting, Q6Length, Q7Email];
if(this.state.i < components.length) this.setState({ i : this.state.i + 1});
}
// handleIncrement() {
// this.setState({ count: this.state.count + 1});
// }}
render() {
const components = [Q1Name, Q2Birthday, Q3City, Q4YouReady, Q5Setting, Q6Length, Q7Email];
const componentsToRender = components.map((Component, i) => (
<Component key={i} />
));
return (
<div className = "container-fluid signup-page">
<div className = "question-box">
{componentsToRender[this.state.i]}
<button type="submit" className="btn btn-custom btn-lg" onClick={() => this._handleClick}>Next Question!</button>
</div>
</div>
);
}
}
export default SignUpPage;
There are a few component types I am bringing in, age, birthday, email, and a few button clicks, etc.
import React from 'react';
class Q1Name extends React.Component {
handleSubmit(event) {
event.preventDefault();
this.props.onNext();
}
render() {
return (
<div className="questions q1" style={this.props.style}>
<h1 id="question-h1">What is your name?</h1>
<form>
<div className="form-group">
<input type="name" className="form-control text-form custom-form" id="nameInput" aria-describedby="name" placeholder="" />
</div>
{/* <button type="submit" className="btn btn-custom btn-lg" onSubmit={this.handleSubmit}>Next Question!</button> */}
</form>
</div>
);
}
}
export default Q1Name;
Here is an example of the button option component:
import React from 'react';
class Q5Setting extends React.Component {
render() {
return (
<div className="questions">
<h1 id="question-h1">What is your ideal setting?</h1>
<button type="button" className="btn btn-custom-select btn-lg">Take me to the beach!</button>
<button type="button" className="btn btn-custom-select btn-lg">Anywhere outdoors!</button>
<button type="button" className="btn btn-custom-select btn-lg">All about the city!</button>
</div>
);
}
}
export default Q5Setting;
Any help in figuring this out would be greatly appreciated!!
In your constructor initialise state
constructor(props) {
super(props)
this.state = { i: 0 }
}
Write helper method handleClick
_handleClick() {
if(this.state.i < components.length) this.setState({ i : this.state.i + 1});
}
Now reference componentsToRender using i in state
`componentsToRender[this.state.i]
Don't forget to call your helper function on click.
onClick = {() => this._handleClick()}
The idea is your app will only re-render when your state object changes. Follow that rule for your components you wish to re-erender on the fry.
I have two text fields and a button using Material-UI, what I want to achieve is to clear the contents of the text fields when I click the button but I don't know how to do it, I'm new to React-JS.
This is the code I have:
import React from 'react';
import RaisedButton from 'material-ui/RaisedButton';
import TextField from 'material-ui/TextField';
export default class CreateLinksave extends React.Component {
render() {
return (
<div clssName="container">
<div>
<TextField floatingLabelText="Receipt Desc" />
</div>
<div>
<TextField floatingLabelText="Triggers Required" />
</div>
<RaisedButton label="Clear" />
</div>
);
}
};
Can someone please help me on this?
the text should be handled by the state
therefore you must only edit the state of the component so that your changes are shown
import React from 'react';
import RaisedButton from 'material-ui/RaisedButton';
import TextField from 'material-ui/TextField';
export default class CreateLinksave extends React.Component {
constructor(props){
super(props);
// initial state
this.state = this.getDefaultState();
}
getDefaultState = () => {
return { text1: '', text2: '' };
}
clear = () => {
// return the initial state
this.setState(this.getDefaultState())
}
render() {
return (
<div className="container">
<div>
<TextField
value={this.state.text1}
onChange={(e)=>{this.setState({text1: e.target.value})}}
floatingLabelText="Receipt Desc"
/>
</div>
<div>
<TextField
onChange={(e)=>{this.setState({text2: e.target.value})}}
value={this.state.text2}
floatingLabelText="Triggers Required"
/>
</div>
// use the clear function
<RaisedButton label="Clear" onClick={this.clear}/>
</div>
);
}
}
If anyone has the same issue with the functional components in React, then you have to handle the value of the Textfield component with a state.
Doesn't matter whether you use Formik library or not.
Simple control the value property of the text field using a state variable.
import React from 'react';
import TextField from '#material-ui/core/TextField';
import Button from '#material-ui/core/Button';
const sampleTextControl = () => {
const [value, setValue] = useState(''); //Initial value should be empty
const handleSubmit = (e)=> {
alert('The value: ' + value);
setValue(''); //To reset the textfield value
e.preventDefault();
}
return (
<form onSubmit={handleSubmit}>
<Textfield id="standard-basic" value={value} onChange={(e)=>setValue(e.target.value)}/>
<Button variant="contained" type="submit" value="Submit">
Submit
</Button>
</form >
)
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
If you don't want to manage state for every text field then you should use refs:
import React from 'react';
import RaisedButton from 'material-ui/RaisedButton';
import TextField from 'material-ui/TextField';
export default class CreateLinksave extends React.Component {
constructor(props) {
super(props);
this.receiptRef = React.createRef('');
this.triggersRef = React.createRef('');
}
handleClick = () => {
this.receiptRef.current.value = null;
this.triggersRef.current.value = null;
}
render() {
return (
<div clssName="container">
<div>
<TextField floatingLabelText="Receipt Desc" />
</div>
<div>
<TextField floatingLabelText="Triggers Required" />
</div>
<RaisedButton label="Clear" onClick={this.handleClick}/>
</div>
);
}
};