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>
);
}
};
Related
I'm new to React. I'm trying to do simple validation of a form elements. I'm stuck at validating input data and setting the 'name_error' state as the error msg inside <p> tag. Leaving my code below
// App.js
import React, { Component } from 'react';
import ValidateName from './component/validation';
import Modal from './modal';
class Home extends Component {
state = {
show: false,
name: "",
name_error: ""
}
handleChanges = (e) => {
const name = e.target.name;
const value = e.target.value;
this.setState({[name] : value})
}
render() {
console.log(this)
return (
<div>
<div className='Main'>
{/* < Main /> */}
<button id='add' onClick={()=>{this.setState({show: true})}}>Add</button>
</div>
{this.state.show &&
<Modal>
<form>
<div className='modalContainer'>
<b className='title'>Register</b>
<button id='xmark' onClick={()=>{this.setState({show: false})}} >×</button>
<label for='name' >Name</label><br />
<input type="text" id='name' placeholder='Enter your name here' name="name" onChange={this.handleChanges}/><br />
< ValidateName content={this.state.name} />
<button type='submit'>Sign Up</button>
<button>Cancel</button>
</div>
</form>
</Modal>}
</div>
);
}
}
export default Home;
// Modal.js
import React, { Component } from 'react';
class Modal extends Component {
render() {
return (
<div>
{this.props.children}
</div>
);
}
}
export default Modal;
//validation.js
class ValidateName extends Component {
err1 ='Please enter any name';
err2 = 'Use only letters in this field';
render() {
const ren = this.props.content.length === 0 ? (<p>{this.err1}</p> ) :
(this.props.content.match(/[a-zA-Z]+$/) ? '' : <p>{this.err2}</p>)
return ren;
}
}
Please suggest an idea to set name_error as 'Please enter any name' or 'Use only letters in this field' when user enters wrong input
State should be like this,
constructor(props){
super(props);
this.state = {
show: false,
name: "",
name_error: ""
}
}
And Also the update state using callback. It would be helpful,
this.setState({[name] : value},() =>{console.log(this.state)})
I'm still a beginner with ReactJS and I need to mirror my switch button in my application.
My switch button change the language from my application, and I have the same button in the header and footer of my pages.
When I change the language from the site, the another button doesn't change at the same time, for example, if I click in my header component to change the language, the button in my footer stay the same way.
I put this example into codesandbox.io
Can you tell me how do I fix the buttons?
import "./styles.scss";
import { I18nProvider } from "./providers/i18n";
import ToggleLanguage from "./components/ToggleLanguage/ToggleLanguage.js";
export default function App() {
return (
<I18nProvider>
<div className="App">
<h3>Example Header</h3>
<ToggleLanguage />
<div style={{ margin: "20px 0" }} />
<h3>Example Footer</h3>
<ToggleLanguage />
</div>
</I18nProvider>
);
}
import React from "react";
import "./ToggleLanguage.scss";
// providers
import { AppContext } from "../../providers/app";
import { saveToStorage } from "../../utils/localStorage";
const ToggleLanguage = () => {
const { state, dispatch } = React.useContext(AppContext);
const onToggleSiteLang = (siteLang) => () => {
dispatch({ type: "setLang", siteLang });
saveToStorage("siteLang", siteLang);
};
return (
<div className="toggle-language">
<label className="switch">
<input
onChange={() => onToggleSiteLang(state.siteLang)}
className="switch-checkbox"
type="checkbox"
/>
<div className="switch-button" />
<div className="switch-labels">
<span>PT</span>
<span>EN</span>
</div>
</label>
</div>
);
};
export default ToggleLanguage;
Thank you very much in advance for any help/tip.
Just control your checkbox with your state. checked={state.siteLang === 'en'}
import React from "react";
import "./ToggleLanguage.scss";
// providers
import { AppContext } from "../../providers/app";
import { saveToStorage } from "../../utils/localStorage";
const ToggleLanguage = () => {
const { state, dispatch } = React.useContext(AppContext);
const onToggleSiteLang = (siteLang) => () => {
dispatch({ type: "setLang", siteLang });
saveToStorage("siteLang", siteLang);
};
return (
<div className="toggle-language">
<label className="switch">
<input
onChange={() => onToggleSiteLang(state.siteLang)}
className="switch-checkbox"
type="checkbox"
checked={state.siteLang === 'en'}
/>
<div className="switch-button" />
<div className="switch-labels">
<span>PT</span>
<span>EN</span>
</div>
</label>
</div>
);
};
export default ToggleLanguage;
Let me know if this works for you
They are working on the game of paper, stone, scissors. I would like to display its id in Result component after pressing one of the buttons. How can I do this?
App.js
import React, { Component } from "react";
import "./App.scss";
import SubmitInfo from "./SubmitInfo";
import ResultInfo from "./ResultInfo";
class App extends Component {
constructor(props) {
super(props);
this.test = this.test.bind(this);
}
test = id => {
//return <Result id={this.props.id}></Result>
console.log("test");
};
render() {
return (
<div>
<div className="board">
<div className="title_row">
<h1 className="title">Kamień, Papier, Nożyce</h1>
</div>
</div>
<div className="board">
<div className="submit_row">
<SubmitInfo id="papier" click={this.test} />
<SubmitInfo id="kamien" click={this.test} />
<SubmitInfo id="nozyce" click={this.test} />
<ResultInfo id={this.test} />
</div>
</div>
</div>
);
}
}
export default App;
SubmitInfo.js
Transfer to id props and click event, Then I render three buttons with different icons.
import React from "react";
import styles from "./submit.scss";
import { FontAwesomeIcon } from "#fortawesome/react-fontawesome";
import {
faHandPaper,
faHandScissors,
faHandRock
} from "#fortawesome/free-solid-svg-icons";
import ResultInfo from "./ResultInfo";
function Submit({ id, click }) {
if (id === "nozyce") {
return (
<button className="submit" onClick={click}>
<FontAwesomeIcon className="icon" icon={faHandScissors} />
</button>
);
} else if (id === "papier") {
return (
<button className="submit" onClick={click}>
<FontAwesomeIcon className="icon" icon={faHandPaper} />
</button>
);
} else if (id === "kamien") {
return (
<button className="submit" onClick={click}>
<FontAwesomeIcon className="icon" icon={faHandRock} />
</button>
);
}
}
export default SubmitInfo;
ResultInfo.js
Here I would like to display the id of the button clicked.
import React, { Component } from "react";
class ResultInfo extends Component {
render(props) {
return (
<div>
{" "}
{this.props.id}
{console.log(this.props.id)}
</div>
//<div></div>
);
}
}
export default ResultInfo;
You should use state. Initialize it in the constructor
constructor(props) {
super(props);
this.state = {
id: null,
};
}
Your test function, should set the state with the id
test = id => {
this.setState({
id,
});
};
ResultInfo component should recieve the state id as an attribute
<ResultInfo id={this.state.id} />
And, the buttons on SubmitInfo component should call the click function, with the id as a parameter
<button className='submit' onClick={() => click(id)}>Rock</button>
David's explanation is correct.
I was working on a codesandbox example on parallel, figured it'd help.
You have some additional errors, like exporting default SubmitInfo instead of Submit, and you can use conditional rendering of ResultInfo component.
I have a menu button that when pressed has to add a new component. It seems to work (if I manually call the function to add the components they are shown). The problem is that if I click the button they are not shown, and I suppose because I should use setState to redraw them. I am not sure how to call the setState of another component within another function/component.
This is my index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import Menu from './Menu';
import * as serviceWorker from './serviceWorker';
import Blocks from './Block.js';
ReactDOM.render(
<div className="Main-container">
<Menu />
<Blocks />
</div>
, document.getElementById('root'));
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers:
serviceWorker.unregister();
Then I have the Menu.js
import React from 'react';
import './Menu.css';
import {blocksHandler} from './Block.js';
class Menu extends React.Component {
constructor(props) {
super(props);
this.state = {value: ''};
this.handleAdd = this.handleAdd.bind(this);
}
handleAdd(event) {
blocksHandler.add('lol');
console.log(blocksHandler.render());
}
render() {
return (
<div className="Menu">
<header className="Menu-header">
<button className="Menu-button" onClick={this.handleAdd}>Add block</button>
</header>
</div>
);
}
}
export default Menu;
And finally the Block.js
import React from 'react';
import './Block.css';
// this function adds components to an array and returns them
let blocksHandler = (function() {
let blocks = [];
return {
add: function(block) {
blocks.push(block);
},
render: function() {
return blocks;
}
}
})();
class Block extends React.Component {
constructor(props) {
super(props);
this.state = {
title: '',
content: ''
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
this.setState({[event.target.name]: event.target.value});
}
handleSubmit(event) {
alert('A name was submitted: ' + this.state.title);
event.preventDefault();
}
render() {
return (
<div className="Block-container">
<form onSubmit={this.handleSubmit}>
<div className="Block-title">
<label>
Block title:
<input type="text" name="title" value={this.state.value} onChange={this.handleChange} />
</label>
</div>
<div className="Block-content">
<label>
Block content:
<input type="text" name="content" value={this.state.value} onChange={this.handleChange} />
</label>
</div>
<input type="submit" value="Save" />
</form>
</div>
);
}
}
class Blocks extends React.Component {
render() {
return (
<div>
{blocksHandler.render().map(i => (
<Block key={i} />
))}
</div>
)
}
}
export default Blocks;
export {blocksHandler};
I am a React complete beginner so I'm not even sure my approach is correct. Thank you for any help you can provide.
Below I've knocked up a really simple Parent / Child type setup,..
The Parent is responsible for rendering the Buttons, I just used a simple numbered array here. When you click any of the buttons, it calls the setState in the Parent, and this in turns causes the Parent to re-render it's Children.
Note: I've also used React Hooks to do this, I just find them more
natural and easier to use. You can use Classes, the same principle
applies.
const {useState} = React;
function Child(props) {
const {caption} = props;
const {lines, setLines} = props.pstate;
return <button onClick={() => {
setLines([...lines, lines.length]);
}}>
{caption}
</button>;
}
function Parent(props) {
const [lines, setLines] = useState([0]);
return lines.map(m => <Child key={m} caption={`Click ${m}`} pstate={{lines, setLines}}/>);
}
ReactDOM.render(<React.Fragment>
<Parent/>
</React.Fragment>, document.querySelector('#mount'));
<script crossorigin src="https://unpkg.com/react#16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom#16/umd/react-dom.development.js"></script>
<div id="mount"></div>
Instead of creating blocksHandlers as a separate function ,you can have it nside the Menu.js like as follows
*
class Block extends React.Component {
constructor(props) {
super(props);
this.state = {
title: '',
content: ''
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
this.setState({[event.target.name]: event.target.value});
}
handleSubmit(event) {
alert('A name was submitted: ' + this.state.title);
event.preventDefault();
}
render() {
return (
<div className="Block-container">
<form onSubmit={this.handleSubmit}>
<div className="Block-title">
<label>
Block title:
<input type="text" name="title" value={this.state.value} onChange={this.handleChange} />
</label>
</div>
<div className="Block-content">
<label>
Block content:
<input type="text" name="content" value={this.state.value} onChange={this.handleChange} />
</label>
</div>
<input type="submit" value="Save" />
</form>
</div>
);
}
}
Menu.js
class Menu extends React.Component {
constructor(props) {
super(props);
this.state = {value: '',blocksArray:[]};
this.handleAdd = this.handleAdd.bind(this);
}
handleAdd() {
this.setState({
blocksArray:this.state.blocksArray.push(block)
})
}
renderBlocks = ()=>{
this.state.blocksArray.map(block=> <Block/>)
}
render() {
return (
<div className="Menu">
<header className="Menu-header">
<button className="Menu-button" onClick={()=>this.handleAdd()}>Add block</button>
</header>
{this.renderBlocks()}
</div>
);
}
}
export default Menu;
I've just started learning React and am struggling with conditional rendering. I want to render components based on form input but i'm not sure what needs to be done or where it needs to be executed.
I have imported my Form component which has the input I want to use and have another component like this:
import React, {Component} from 'react';
import Form from './Form';
import CardOne from './CardOne';
import CardTwo from './CardTwo';
import CardThree from './CardThree';
export default class CardContainer extends Component {
render(){
return (
<div>
<CardOne />
<CardTwo />
<CardThree />
</div>
)
}
}
I basically want to be able to show certain Cards if the value of the input is greater than X when the form is submitted, but I don't know how to target an imported component.
This is my Form component:
export default class Form extends Component {
state = {
number: ''
};
change = (e) => {
this.setState({
[e.target.name]: e.target.value
});
};
onSubmit = e => {
e.preventDefault();
this.props.onSubmit(this.state);
this.setState({
number: ''
})
};
render(){
return (
<form>
<label>Number</label>
<input
type="number"
name="number"
placeholder="Number"
value={this.state.number}
onChange={e => this.change(e)} />
<button onClick={e => this.onSubmit(e)}>Submit</button>
</form>
)
}
}
Any help will be massively appreciated!
I have redesigned your Form component , Below is my code. . Let me know if u faced any issues on that .
import React, { Component } from 'react';
import CardOne from './CardOne';
import CardTwo from './CardTwo';
import CardThree from './CardThree';
export default class Form extends Component {
state = {
number: '',
showOne:true,
showTwo:false,
showThree:false,
userInputValue:''
};
change = (e) => {
this.setState({
userInputValue: e.target.value
});
};
onSubmit = e => {
e.preventDefault();
this.props.onSubmit(this.state);
if (this.state.userInputValue > 10 && this.state.userInputValue <20 ){
this.setState({
showTwo: true,
})
}
if (this.state.userInputValue > 20 && this.state.userInputValue < 30) {
this.setState({
showThree: true,
})
}
};
render() {
return (
<div>
<form>
<label>Number</label>
<input
type="number"
name="number"
placeholder="Number"
value={this.state.userInputValue}
onChange={e => this.change(e)} />
<button onClick={e => this.onSubmit(e)}>Submit</button>
</form>
<div>
{this.state.showOne ?
<CardOne />
:
<div></div>
}
{this.state.showTwo ?
<CardTwo />
:
<div></div>
}
{this.state.showThree ?
<CardThree />
:
<div></div>
}
</div>
</div>
)
}
}
// What i wrote above is your base functionality . You reedit the condition depends on ur requirement .
This is what I came up with following your logic of card rendering. I did not change Form coponent but rather worked on the Container
export default class CardContainer extends Component {
constructor(props) {
super(props);
state = {
number: 0,
}
this.onFormSubmit = this.onFormSubmit.bind(this);
}
onFormSubmit=(number)=>{
this.setState({ number: number });
}
render(){
let i=Math.floor(this.state.number/10)
return (
<div>
<Form onSubmit={() => this.onFormSubmit(number)}
[<CardOne />, <CardTwo />, <CardThree/>].slice(0,i).map(card =>
{card}
)
</div>
)
}
}
I would use render prop for this kind of problem. You can research more about render props but basically your CardContainer component will not render those cards component statically as it is. It will return props.children instead.
And then you will have a function (i.e function TestX) that will have a conditional to check what the value of X is. This is the function that will return either , , based on what X is. The function TestX will receive props from CardContainer, including the value of X that is read from the state.
So I will just use CardContainer component with as its child.