ng-model
, ngIf
and ngFor
. This code looks rather cumbersome. In React, on the other hand, JSX syntax is used, which is perceived as plain HTML, that is, in order to start React development, you do not need to learn fundamentally new things. Here's what it looks like: const Greetings = ({ firstName }) => ( <div>Hi, {firstName}</div> );
create-react-app
package from Facebook to create the basis of the React application. This is probably the most popular approach to setting up the working environment, which allows you to start developing. Thanks to create-react-app
programmer has at his disposal many of the necessary tools, which saves him from having to select them himself.create-react-app
, use the following command: npm i -g create-react-app
create-react-app react-intro
cd react-intro npm start
public/index.html
. Here is what you see when you do this.<div id="root">
. This is where our React application will be located. All this element will be replaced with the application code, and everything else will remain unchanged.src/index.js
. This file performs the deployment of React-application. And, by the way, the source code of the application will be located in the src
directory. ReactDOM.render(<App />, document.getElementById('root'));
App
component (we'll talk about it very soon) and put it in the root
div
, which was defined in the index.html
file we just reviewed.<App />
. It is very similar to HTML code, but it is a sample of JSX code that represents the special JavaScript syntax used by React. Please note that this construction starts with a capital A
, that this is <App />
, not <app />
. This is because of the entity naming convention used in React. This approach allows the system to distinguish between ordinary HTML tags and React components. If component names do not begin with a capital letter, React will not be able to display them on the page..js
file, you need to import React there using the following command: import React from 'react';
src/App.js
React.Component
. This is exactly the task that the class App extends Component
solves. All React components should contain an implementation of the render
method, in which, as its name suggests, the component is rendered and its visual presentation is formed. This method should return HTML markup to display it on the page.className
attribute is the equivalent of the class
attribute in HTML. It is used to assign CSS class elements for styling. The class
keyword in javascript is reserved; it cannot be used as an attribute name.A
in the App
).React.Component
class.render
method that returns the markup.render
method, then it is an excellent contender for processing it into a functional component. Armed with this idea, let's think about how to improve the App
component created by the create-react-app
tool: function App() { return ( <div className="App"> ... </div> ); } export default App;
render
method with the view structure function App() {...}
. If we use the syntax of ES6 switch functions, then our code will look even better: const App = () => ( <div className="App"> ... </div> ); export default App;
const Greetings = (props) => <div>Hey you! {props.firstName} {props.lastName}!</div>; const App = () => ( <div> <Greetings firstName="John" lastName="Smith" /> </div> );
Greetings
component and used it to greet the person, whose name is John Smith
, from the App
component. All this code will result in the following HTML markup: <div> <div>Hey you! John Smith!</div> </div>
{props.name}
are used to extract JavaScript code. Greetings
are passed to the firstName
and lastName
properties as parameters. We work with them by referring to the properties of the props
object.props
object is props
, rather than two values ​​representing the properties firstName
and lastName
. const Greetings = ({ firstName, lastName }) => <div>Hey you! {firstName} {lastName}!</div>;
(props)
was replaced by ({ firstName, lastName })
. With this replacement, we inform the system that we are only interested in two properties of the props
object. And this, in turn, allows us to directly access the values ​​of firstName
and lastName
, without explicitly specifying properties of an object like props.firstName
.Greetings
component code would look like this: class Greetings extends React.Component { render() { return ( <div>Hey you! {this.props.firstName} {this.props.lastName}!</div> ); } }
this.props
.Greetings
and the App
is in the same file. In practice, this should not be done, as this violates the SRP.Greetings
component) need to be placed in separate files.Greetings
component in a separate file: import React from "react"; const Greetings = ({ firstName, lastName }) => ( <div> Hey you! {firstName} {lastName}! </div> ); export default Greetings;
App
component: import Greetings from "./Greetings"; const App = () => ( ... );
App
component code must be placed in the App.js
file, the Greetings
component code is in the Greetings.js
file, and so on. import React from "react"; class SimpleForm extends React.Component { render() { return ( <div> <input type="text" name="firstName" /> <Greetings firstName="John" /> </div> ); } } const App = () => ( <div> <SimpleForm /> </div> );
John
is always used as the username in the welcome page. What if so far not all our users call this? If so, then we put ourselves in a not very comfortable position. class SimpleForm extends React.Component { state = { firstName: "", }; onFirstNameChange = event => this.setState({ firstName: event.target.value }); render() { return ( <div> <input type="text" name="firstName" onChange={this.onFirstNameChange} /> <Greetings firstName={this.state.firstName} /> </div> ); } }
SimpleForm
component SimpleForm
. In this object we add the property firstName
.firstName
field with an event handler. It starts every time the user enters at least one character in the field. In the class, the onChange
property is responsible for handling the onChange
onFirstNameChange
, in the function representing which the command is executed of the following form: this.setState(...)
setState
method. In order to write a new value to the property firstName
, we simply pass to this method an object containing what needs to be written to the state: { firstName: event.target.value }
event.target.value
is what the user entered in the form field, namely his name.onFirstNameChange
as a method. It is very important that such things be declared in the form of class properties containing pointer functions, and not in the form of methods. If you declare a similar function as a method, then this
will be bound to the form element that calls this method, and not to the class, as we might expect. This little thing is often confusing for beginners. This is one of the reasons for recommending the use of functional components, rather than component classes.onBlur
event handler to the component, which is called when the user leaves the input field. Add another property to the application state - firstNameError
. If an error occurred while entering the name, we will display a message about it under the field. class SimpleForm extends React.Component { state = { firstName: "", firstNameError: "", }; validateName = name => { const regex = /[A-Za-z]{3,}/; return !regex.test(name) ? "The name must contain at least three letters. Numbers and special characters are not allowed." : ""; }; onFirstNameBlur = () => { const { firstName } = this.state; const firstNameError = this.validateName( firstName ); return this.setState({ firstNameError }); }; onFirstNameChange = event => this.setState({ firstName: event.target.value }); render() { const { firstNameError, firstName } = this.state; return ( <div> <div> <label> First name: <input type="text" name="firstName" onChange={this.onFirstNameChange} onBlur={this.onFirstNameBlur} /> {firstNameError && <div>{firstNameError}</div>} </label> </div> <Greetings firstName={firstName} /> </div> ); } }
firstNameError
to the state: state = { ... firstNameError: "", };
validateName
arrow function. It checks the entered name with a regular expression: validateName = name => { const regex = /[A-Za-z]{3,}/; return !regex.test(name) ? "The name must contain at least three letters..." : ""; }
onBlur
look at the onBlur
event onBlur
, which is called when the user leaves the input field: onFirstNameBlur = () => { const { firstName } = this.state; const firstNameError = this.validateName( firstName ); return this.setState({ firstNameError }); };
firstName
property from the state, taking advantage of ES6's ability to destruct the objects. The first line of this code is equivalent to: const firstName = this.state.firstName;
firstName
, and write to the state property firstNameError
what this function returns. If the check fails, an error message will be sent to this property. If successful, an empty string will be written there.render()
component method: render() { const { firstNameError, firstName} = this.state; ... }
<input ... onBlur={this.onFirstNameBlur} />
onFirstNameBlur
onBlur
. {firstNameError && <div>{firstNameError}</div>}
div
, , , firstNameError
true
. render() { const { firstNameError, firstName } = this.state; return ( <div style={{ margin: 50, padding: 10, width: 300, border: "1px solid black", backgroundColor: "black", color: "white" }} > <div style={{marginBottom: 10}}> <label> First name: <input style={{backgroundColor: '#EFEFFF', marginLeft: 10}} type="text" name="firstName" onChange={this.onFirstNameChange} onBlur={this.onFirstNameBlur} /> {firstNameError && <div style={{color: 'red', margin: 5}}>{firstNameError}</div>} </label> </div> <Greetings firstName={firstName} /> </div> ); }
style
.render
, , . Why is that bad? , . , , .style
, . . , style.js
: // style.js: const style = { form: { margin: 50, padding: 10, width: 300, border: "1px solid black", backgroundColor: "black", color: "white" }, inputGroup: { marginBottom: 10 }, input: { backgroundColor: "#EFEFFF", marginLeft: 10 }, error: { color: "red", margin: 5 } }; export default style;
SimpleComponent
: import style from './style'; class SimpleForm extends React.Component { ... render() { const { firstNameError, firstName } = this.state; return ( <div style={style.form}> <div style={style.inputGroup}> <label> First name: <input style={style.input} type="text" name="firstName" onChange={this.onFirstNameChange} onBlur={this.onFirstNameBlur} /> {firstNameError && ( <div style={style.error}>{firstNameError}</div> )} </label> </div> <Greetings firstName={firstName} /> </div> ); } } export default SimpleForm;
class SimpleForm extends React.Component { state = { ... lastName: "", lastNameError: "" }; validateName = ...; onFirstNameBlur = ...; onFirstNameChange = ...; onLastNameBlur = () => { const { lastName } = this.state; const lastNameError = this.validateName(lastName); return this.setState({ lastNameError }); }; onLastNameChange = event => this.setState({ lastName: event.target.value }); render() { const { firstNameError, firstName, lastName, lastNameError } = this.state; return ( <div style={style.form}> <div style={style.inputGroup}> <label> First name: <input style={style.input} type="text" name="firstName" onChange={this.onFirstNameChange} onBlur={this.onFirstNameBlur} /> {firstNameError && <div style={style.error}>{firstNameError}</div>} </label> </div> <div style={style.inputGroup}> <label> Last name: <input style={style.input} type="text" name="lastName" onChange={this.onLastNameChange} onBlur={this.onLastNameBlur} /> {lastNameError && <div style={style.error}>{lastNameError}</div>} </label> </div> <Greetings firstName={firstName} lastName={lastName} /> </div> ); } } export default SimpleForm;
firstName
.render
. .TextField
, . import React from 'react' import style from "./style"; const TextField = ({name, onChange, onBlur, error, label}) => ( <div style={style.inputGroup}> <label> {label} <input style={style.input} type="text" name={name} onChange={onChange} onBlur={onBlur} /> {error && <div style={style.error}>{error}</div>} </label> </div> ); export default TextField;
render
. , , .SimpleForm
: ... import TextField from './TextField'; class SimpleForm extends React.Component { ... render() { const { firstNameError, firstName, lastName, lastNameError } = this.state; return ( <div style={style.form}> <TextField name="firstName" label="First name:" onChange={this.onFirstNameChange} onBlur={this.onFirstNameBlur} error={firstNameError} /> <TextField name="lastName" label="Last name:" onChange={this.onLastNameChange} onBlur={this.onLastNameBlur} error={lastNameError} /> <Greetings firstName={firstName} lastName={lastName} /> </div> ); } }
TextField
. FirstNameField
: import React from 'react'; import TextField from './TextField'; const FirstNameField = ({...rest}) => ( <TextField name="firstName" label="First name:" {...rest} /> ); export default FirstNameField;
({...rest})
( rest, ). , , , rest
. , , TextField
, « », spread (, {...rest}
, ). rest
, , TextField
.FirstNameField
TextField
.LastNameField
: ... import FirstNameField from './FirstNameField'; import LastNameField from './LastNameField'; class SimpleForm extends React.Component { ... render() { const { firstNameError, firstName, lastName, lastNameError } = this.state; return ( <div style={style.form}> <FirstNameField onChange={this.onFirstNameChange} onBlur={this.onFirstNameBlur} error={firstNameError} /> <LastNameField onChange={this.onLastNameChange} onBlur={this.onLastNameBlur} error={lastNameError} /> <Greetings firstName={firstName} lastName={lastName} /> </div> ); } }
this
, .Source: https://habr.com/ru/post/428077/
All Articles