npx create-react-app meme-generator
index.js
and App.js
. You can easily delete this code and try to write it yourself in order to test yourself in the implementation of standard mechanisms of React-applications. * { box-sizing: border-box; } body { margin: 0; background-color: whitesmoke; } header { height: 100px; display: flex; align-items: center; background: #6441A5; /* fallback for old browsers */ background: -webkit-linear-gradient(to right, #2a0845, #6441A5); /* Chrome 10-25, Safari 5.1-6 */ background: linear-gradient(to right, #2a0845, #6441A5); /* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */ } header > img { height: 80%; margin-left: 10%; } header > p { font-family: VT323, monospace; color: whitesmoke; font-size: 50px; margin-left: 60px; } .meme { position: relative; width: 90%; margin: auto; } .meme > img { width: 100%; } .meme > h2 { position: absolute; width: 80%; text-align: center; left: 50%; transform: translateX(-50%); margin: 15px 0; padding: 0 5px; font-family: impact, sans-serif; font-size: 2em; text-transform: uppercase; color: white; letter-spacing: 1px; text-shadow: 2px 2px 0 #000, -2px -2px 0 #000, 2px -2px 0 #000, -2px 2px 0 #000, 0 2px 0 #000, 2px 0 0 #000, 0 -2px 0 #000, -2px 0 0 #000, 2px 2px 5px #000; } .meme > .bottom { bottom: 0; } .meme > .top { top: 0; } .meme-form { width: 90%; margin: 20px auto; display: flex; justify-content: space-between; } .meme-form > input { width: 45%; height: 40px; } .meme-form > button { border: none; font-family: VT323, monospace; font-size: 25px; letter-spacing: 1.5px; color: white; background: #6441A5; } .meme-form > input::-webkit-input-placeholder { /* Chrome/Opera/Safari */ font-family: VT323, monospace; font-size: 25px; text-align: cen } .meme-form > input::-moz-placeholder { /* Firefox 19+ */ font-family: VT323, monospace; font-size: 25px; text-align: cen } .meme-form > input:-ms-input-placeholder { /* IE 10+ */ font-family: VT323, monospace; font-size: 25px; text-align: cen } .meme-form > input:-moz-placeholder { /* Firefox 18- */ font-family: VT323, monospace; font-size: 25px; text-align: cen }
index.css
file already present in the project and index.css
in the index.js
file.index.js
and App.js
files are now empty, you, as the first task, are invited to write the index.js
code index.js
, create the simplest component in App.js
and display it in index.js
.index.js
: import React from "react" import ReactDOM from "react-dom" import './index.css' import App from "./App" ReactDOM.render(<App />, document.getElementById("root"))
React
and ReactDOM
, import styles from index.css
and the App
component. After that, using the ReactDOM.render()
method, we ReactDOM.render()
what the App
component forms into the element of the index.html
page with the root
identifier ( <div id="root"></div>
).App.js
file looks like: import React from "react" function App() { return ( <h1>Hello world!</h1> ) } export default App
Header
component that will be used to display the application header.MemeGenerator
, which will solve the main tasks assigned to the application. Namely, API calls will be made here. The application data will also be stored here.Header.js
file: import React from "react" function Header() { return ( <h1>HEADER</h1> ) } export default Header
MemeGenerator.js
file: import React, {Component} from "react" class MemeGenerator extends Component { constructor() { super() this.state ={} } render() { return ( <h1>MEME GENERATOR SECTION</h1> ) } } export default MemeGenerator
MemeGenerator
component, will use the component based on the class. There is a constructor in which we initialize the state with an empty object.App.js
and return the markup from the functional component App
, which uses instances of these components, not forgetting that if the functional component returns several elements, they need to be wrapped into something. In our case, this is the <div>
. Here is the updated App.js
code: import React from "react" import Header from "./Header" import MemeGenerator from "./MemeGenerator" function App() { return ( <div> <Header /> <MemeGenerator /> </div> ) } export default App
Header
component. Here we use the HTML5 <header>
semantic element. This tag will contain the image and text. Now the code of the Header.js
file will look like this: import React from "react" function Header() { return ( <header> <img src="http://www.pngall.com/wp-content/uploads/2016/05/Trollface.png" alt="Problem?" /> <p>Meme Generator</p> </header> ) } export default Header
index.js
. The work on the Header
component is now complete.MemeGenerator
. Now you are invited to independently initialize the state of this component by writing the following data into it:topText
property).bottomText
property).randomImage
property, which needs to be initialized by the link http://i.imgflip.com/1bij.jpg ).MemeGenerator.js
code will be after the state is initialized: import React, {Component} from "react" class MemeGenerator extends Component { constructor() { super() this.state = { topText: "", bottomText: "", randomImg: "http://i.imgflip.com/1bij.jpg" } } render() { return ( <h1>MEME GENERATOR SECTION</h1> ) } } export default MemeGenerator
MemeGenerator
component:response.data.memes
in a new state property ( allMemeImgs
). { "success":true, "data":{ "memes":[ { "id":"112126428", "name":"Distracted Boyfriend", "url":"https:\/\/i.imgflip.com\/1ur9b0.jpg", "width":1200, "height":800, "box_count":3 }, { "id":"87743020", "name":"Two Buttons", "url":"https:\/\/i.imgflip.com\/1g8my4.jpg", "width":600, "height":908, "box_count":2 }, { "id":"129242436", "name":"Change My Mind", "url":"https:\/\/i.imgflip.com\/24y43o.jpg", "width":482, "height":361, "box_count":2 }, β¦. ] } }
componentDidMount()
. Here we will use the standard fetch()
method to access the API. It returns a promise. After the data is loaded, the response object will be available to us, we extract the memes
array from it and put it in the new state property allMemeImgs
, initialized with an empty array. Since this data is not yet used to form something that is displayed on the screen, we will display the first element of the array in the console to check the correctness of the data loading mechanism.MemeGenerator
component at this stage of the work: import React, {Component} from "react" class MemeGenerator extends Component { constructor() { super() this.state = { topText: "", bottomText: "", randomImg: "http://i.imgflip.com/1bij.jpg", allMemeImgs: [] } } componentDidMount() { fetch("https://api.imgflip.com/get_memes") .then(response => response.json()) .then(response => { const {memes} = response.data console.log(memes[0]) this.setState({ allMemeImgs: memes }) }) } render() { return ( <h1>MEME GENERATOR SECTION</h1> ) } } export default MemeGenerator
url
property, which gives access to the link to download the image.MemeGenerator
component code shown below, which differs from the above code of this component in that the form blank has been added here, create a couple of text fields, topText
and bottomText
. Note that these must be managed components. Add the necessary attributes to them. Create an onChange
event onChange
these fields, where you need to update the corresponding state properties as you enter text in them. import React, {Component} from "react" class MemeGenerator extends Component { constructor() { super() this.state = { topText: "", bottomText: "", randomImg: "http://i.imgflip.com/1bij.jpg", allMemeImgs: [] } } componentDidMount() { fetch("https://api.imgflip.com/get_memes") .then(response => response.json()) .then(response => { const {memes} = response.data this.setState({ allMemeImgs: memes }) }) } render() { return ( <div> <form className="meme-form"> { // } <button>Gen</button> </form> </div> ) } } export default MemeGenerator
render()
method, we enclosed it in braces in order to indicate to the system that it should take the given fragment as JavaScript code. import React, {Component} from "react" class MemeGenerator extends Component { constructor() { super() this.state = { topText: "", bottomText: "", randomImg: "http://i.imgflip.com/1bij.jpg", allMemeImgs: [] } this.handleChange = this.handleChange.bind(this) } componentDidMount() { fetch("https://api.imgflip.com/get_memes") .then(response => response.json()) .then(response => { const {memes} = response.data this.setState({ allMemeImgs: memes }) }) } handleChange(event) { const {name, value} = event.target this.setState({ [name]: value }) } render() { return ( <div> <form className="meme-form"> <input type="text" name="topText" placeholder="Top Text" value={this.state.topText} onChange={this.handleChange} /> <input type="text" name="bottomText" placeholder="Bottom Text" value={this.state.bottomText} onChange={this.handleChange} /> <button>Gen</button> </form> </div> ) } } export default MemeGenerator
console.log()
command.Gen
button, randomly select an image from this array and form a meme.MemeGenerator
component. Here, in the render()
method, below the form description code, there is a <div>
element that includes an <img>
element that displays an image, and a pair of <h2>
elements that display labels. The <div>
and <h2>
elements are designed using the styles that we added to the project at the very beginning of working on it. import React, {Component} from "react" class MemeGenerator extends Component { constructor() { super() this.state = { topText: "", bottomText: "", randomImg: "http://i.imgflip.com/1bij.jpg", allMemeImgs: [] } this.handleChange = this.handleChange.bind(this) } componentDidMount() { fetch("https://api.imgflip.com/get_memes") .then(response => response.json()) .then(response => { const {memes} = response.data this.setState({ allMemeImgs: memes }) }) } handleChange(event) { const {name, value} = event.target this.setState({ [name]: value }) } render() { return ( <div> <form className="meme-form"> <input type="text" name="topText" placeholder="Top Text" value={this.state.topText} onChange={this.handleChange} /> <input type="text" name="bottomText" placeholder="Bottom Text" value={this.state.bottomText} onChange={this.handleChange} /> <button>Gen</button> </form> <div className="meme"> <img align="center" src={this.state.randomImg} alt="" /> <h2 className="top">{this.state.topText}</h2> <h2 className="bottom">{this.state.bottomText}</h2> </div> </div> ) } } export default MemeGenerator
allMemeImgs
. Let's try to enter something in the text fields.Gen
button from the array with the image data, a random image would be selected and loaded into the <img>
element present on the page below the text input fields.Gen
button. This method should choose one of the images, information about which is stored in the state property allMemeImgs
, and then perform actions that allow you to display this image in the <img>
element located below the text input fields. allMemeImgs
in allMemeImgs
that allMemeImgs
stores an array of objects that describe images, and that each object from this array has a url
property. import React, {Component} from "react" class MemeGenerator extends Component { constructor() { super() this.state = { topText: "", bottomText: "", randomImg: "http://i.imgflip.com/1bij.jpg", allMemeImgs: [] } this.handleChange = this.handleChange.bind(this) this.handleSubmit = this.handleSubmit.bind(this) } componentDidMount() { fetch("https://api.imgflip.com/get_memes") .then(response => response.json()) .then(response => { const {memes} = response.data this.setState({ allMemeImgs: memes }) }) } handleChange(event) { const {name, value} = event.target this.setState({ [name]: value }) } handleSubmit(event) { event.preventDefault() const randNum = Math.floor(Math.random() * this.state.allMemeImgs.length) const randMemeImg = this.state.allMemeImgs[randNum].url this.setState({ randomImg: randMemeImg }) } render() { return ( <div> <form className="meme-form" onSubmit={this.handleSubmit}> <input type="text" name="topText" placeholder="Top Text" value={this.state.topText} onChange={this.handleChange} /> <input type="text" name="bottomText" placeholder="Bottom Text" value={this.state.bottomText} onChange={this.handleChange} /> <button>Gen</button> </form> <div className="meme"> <img align="center" src={this.state.randomImg} alt="" /> <h2 className="top">{this.state.topText}</h2> <h2 className="bottom">{this.state.bottomText}</h2> </div> </div> ) } } export default MemeGenerator
Gen
button can be assigned an event handler that occurs when you click on it, as is done when working with any other buttons. However, given that this button is used to submit the form, it would be better to use the form's onSubmit
event handler. In this handler, handleSubmit()
, we call the event event event.preventDefault()
to cancel the standard form event.preventDefault()
procedure during which the page is reloaded. Next, we get a random number in the range from 0 to the value corresponding to the index of the last element of the array allMemeImgs
and use this number to refer to the element with the corresponding index. Referring to the element that is an object, we get the property of this object url
and write it in the state property randomImg
. After that, the component is re-rendered and the page appearance changes.Source: https://habr.com/ru/post/447136/
All Articles