Planet MySQL

Planet MySQL - https://planet.mysql.com
  1. Just a friendly reminder for another two shows where you can find MySQL team at this week.  Feira do Conhecimento Brazil is a unique event with more than 10.000 attendees. There will be about 200 exhibitors on 9000m2 of expo space presenting technological solutions to improve key areas for society such as health, education, cities, agriculture, water resources, renewable energies, inclusion and diversity. The show will bring together academia, business, government and community to show how science and technology can help reduce inequalities. We are happy to be part of this show with our talk and MySQL representative! Place: Fortaleza, Brazil Date: November 21-24, 2018 Approved Talk: "Innovation, Business & Technology"  PyCon HK where MySQL Community is a Bronze sponsor. See details below: Place: Hong Kong Date: November 23-24, 2018 MySQL talk: "NoSQL Development for MySQL Document Store using Python" by Ivan Ma, the MySQL Principal Sales Consultant​
  2. Today I read the nice post of Bhuvanesh on the memory leak issue they experienced with MySQL. In fact when you read the post, you realize that MySQL was just following the parameters that were setup (the default of max_prepare_stmt_count is 16382 even on 5.6). I’m still convinced that the problem should be resolved in the application even if the use of ProxySQL for multiplexing is great. In MySQL 8.0, we have enabled the memory instrumentation by default (see this post) and it’s possible to see the memory allocation for all threads having open prepare statements. I modified the query described in this post and added the memory consumption: USE performance_schema; SELECT t.thread_id, user,current_count_used, current_allocated, current_avg_alloc, sp.count_star - sd.count_star open_sql_prepared, cp.count_star - cc.count_star open_com_prepared FROM ( SELECT COUNT_STAR, THREAD_ID FROM events_statements_summary_by_thread_by_event_name WHERE event_name = 'statement/sql/prepare_sql' ) sp JOIN ( SELECT COUNT_STAR, THREAD_ID FROM events_statements_summary_by_thread_by_event_name WHERE event_name = 'statement/com/Prepare' ) cp ON (cp.THREAD_ID = sp.THREAD_ID) JOIN ( SELECT COUNT_STAR, THREAD_ID FROM events_statements_summary_by_thread_by_event_name WHERE event_name = 'statement/sql/dealloc_sql' ) sd ON (sd.THREAD_ID = sp.THREAD_ID) JOIN ( SELECT COUNT_STAR, THREAD_ID FROM events_statements_summary_by_thread_by_event_name WHERE event_name = 'statement/com/Close stmt' ) cc ON (cc.THREAD_ID = sp.THREAD_ID) JOIN sys.memory_by_thread_by_current_bytes t on t.thread_id = sp.thread_id WHERE sp.count_star - sd.count_star <> 0 OR cp.count_star - cc.count_star <> 0; And the result is the following: +-----------+----------------+--------------------+-------------------+-------------------+-------------------+-------------------+ | thread_id | user | current_count_used | current_allocated | current_avg_alloc | open_sql_prepared | open_com_prepared | +-----------+----------------+--------------------+-------------------+-------------------+-------------------+-------------------+ | 58 | root@localhost | 207 | 1.74 MiB | 8.62 KiB | 1 | 0 | | 61 | root@localhost | 43 | 82.48 KiB | 1.92 KiB | 19 | 0 | | 62 | root@localhost | 23 | 72.69 KiB | 3.16 KiB | 6 | 0 | +-----------+----------------+--------------------+-------------------+-------------------+-------------------+-------------------+ As you can see, MySQL 8.0 instrumentation allows you to find almost everything you need ! If you have extra needs, please let us know
  3. This is review of TRIAD which was published in USENIX ATC 2017. It explains how to reduce write amplification for RocksDB leveled compaction although the ideas are useful for many LSM implementations. I share a review here because the paper has good ideas. It isn't easy to keep up with all of the LSM research, even when limiting the search to papers that reference RocksDB, and I didn't notice this paper until recently.TRIAD reduces write amplification for an LSM with leveled compaction and with a variety of workloads gets up to 193% more throughput, up to 4X less write amplification and spends up to 77% less time doing compaction and flush. Per the RUM Conjecture improvements usually come at a cost and the cost in this case is more cache amplification (more memory overhead/key) and possibly more read amplification. I assume this is a good tradeoff in many cases.The paper explains the improvements via 3 components -- TRIAD-MEM, TRIAD-DISK and TRIAD-LOG -- that combine to reduce write amplification.TRIAD-MEMTRIAD-MEM reduces write-amp by keeping frequently updated keys (hot keys) in the memtable. It divides keys into the memtable into two classes: hot and cold. On flush the cold keys are written into a new L0 SST while the hot keys are copied over to the new memtable. The hot keys must be written again to the new WAL so that the old WAL can be dropped. TRIAD-MEM tries to keep the K hottest keys in the memtable and there is work in progress to figure out a good value for K without being told by the DBA.An extra 4-bytes/key is used for the memtable to track write frequency and identify hot keys. Note that RocksDB already 8 bytes/key for metadata. So TRIAD-MEM has a cost in cache-amp but I don't think that is a big deal.Assuming the per-level write-amp is 1 from the memtable flush this reduces it to 0 in the best case where all keys are hot.TRIAD-DISKTRIAD-DISK reduces write-amp by delaying L0:L1 compaction until there is sufficient overlap between keys to be compacted. TRIAD continues to use an L0:L1 compaction trigger based on the number of files in the L0 but can trigger compaction earlier when there is probably sufficient overlap between the L0 and L1 SSTs.Overlap is estimated via Hyperloglog (HLL) which requires 4kb/SST and is estimated as the following where file-i is the i-th SST under consideration, UniqueKeys is the estimated number of distinct keys across all of the SSTs and Keys(file-i) is the number of keys in the i-th SST. The paper states that both UniqueKeys and Keys are approximated using HLL. But I assume that per-SST metadata already has an estimate or exact value for the number of keys in the SST. The formula for overlap is:    UniqueKeys(file-1, file-2,... file-n) / sum( Keys( file-i))The benefit from early L0:L1 compaction is less read-amp, because there will be fewer sorted runs to search on a query. The cost from always doing early compaction is more per-level write-amp which is etimated by size(L1 input) / size(L0 input). TRIAD-DISK provides the benefit with less cost.In RocksDB today you can manually schedule early compaction by setting the trigger to 1 or 2 files, or you can always schedule it to be less early with a trigger set to 8 or more files. But this setting is static. TRIAD-DISK uses a cost-based approach to do early compaction when it won't hurt the per-level write-amp. This is an interesting idea.TRIAD-LOGTRIAD-LOG explains improvements to memtable flush that reduce write-amp. Data in an L0 SST has recently been written to the WAL. So they use the WAL in place of writing the L0 SST. But something extra, an index into the WAL, is written on memtable flush because everything in the L0 must have an index. The WAL in the SST (called the CL-SST for commit log SST) will be deleted when it is compacted into the L1.There is cache-amp from TRIAD-LOG. Each key in the CL-SST (L0) and maybe in the memtable needs 8 extra bytes -- 4 bytes for CL-SST ID, 4 bytes for the WAL offset.Assuming the per-level write-amp is one from the memtable flush for cold keys this reduces that to 0.Reducing write amplificationThe total write-amp for an LSM tree with leveled compaction is the sum of: writing the WAL = 1 memtable flush = 1 L0:L1 compaction ~= size(L1) / size(L0) Ln compaction for n>1 ~= fanout, the per-level growth factor, usually 8 or 10. Note that this paper explains why it is usually a bit less than fanout. TRIAD avoids the write-amp from memtable flush thanks to TRIAD-MEM for hot keys and TRIAD-LOG for cold keys. I will wave my hands and suggest that TRIAD-DISK reduces write-amp for L0:L1 from 3 to 1 based on the typical LSM configuration I use. So TRIAD reduces the total write-amp by 1+2 or 3.Reducing total write-amp by 3 is a big deal when the total write-amp for the LSM tree is small, for example <= 10. But that only happens when there are few levels beyond the L1. Assuming you accept my estimate for total write-amp above then per-level write-amp is ~8 for both L1:L2 and L2:L3. The total write-amp for an LSM tree without TRIAD would be 1+1+3+8 = 13 if the max level is L2 and 1+1+3+8+8 = 21 if the max level is L3. And then TRIAD reduces that from 13 to 10 or from 21 to 18.But my write-amp estimate above is more true for workloads without skew and less true for workloads with skew. Many of the workloads tested in the paper have a large amount of skew. So while I have some questions about the paper I am not claiming they are doing it wrong. What I am claiming is that the benefit from TRIAD is significant when total write-amp is small and less significant otherwise. Whether this matters is workload dependent. It would help to know more about the LSM tree from each benchmark. How many levels were in the LSM tree per benchmark? What is the per-level write-amp with and without TRIAD? Most of this can be observed from compaction statistics provided by RocksDB. The paper has some details on the workloads but that isn't sufficient to answer the questions above. QuestionsThe paper documents the memory overhead, but limits the definition of read amplification to IO and measured none. I am interested in IO and CPU and suspect there might be some CPU read-amp from using the commit-log SST in the L0 both for searches and during compaction as logically adjacent data is no longer physically adjacent in the commit-log SST.impact of more levels?Another question is how far down the LSM compaction occurs. For example if the write working set fits in the L2, should compaction stop at the L2. It might with some values of compaction priority in RocksDB but it doesn't for all.  When the workload has significant write skew then the write working set is likely to fit into one of the smaller levels of the LSM tree.An interesting variant on this is a workload with N streams of inserts that are each appending (right growing). When N=1 there is an optimization in RocksDB that limits write-amp to 2 (one for WAL, one for SST). I am not aware of optimizations in RocksDB for N>2 but am curious if we could do something better.
  4. I am currently working my way through the many PHP Frameworks to see how they get on with MySQL 8.  The Frameworks that can take advantage of the MySQL Improved Extension or mysqli can take advantage of the SHA256 Caching Authentication method. But those that are PDO based need to use the older MySQL Native Authentication method.I wanted to check the PDO based frameworks and today I just happened to be wearing the very nice Symfony shirt I received as part of my presentation at Symfony USA.  So I started with a fresh install of Symfony.  All was going well until it came time to get it to work with MySQL 8 through Doctrine.Doctrine Symfony uses Doctrine as an ORM (Object Relational Mapper) and DBAL  (Database Abstraction Layer) as an intermediary to the database.  While I myself am not a big fan of ORMs Doctrine does manage version migration very nicely.  When I tried to tie the frame work and the database together I received a stern connection refused error.So I double checked the database connection parameters, making sure that I could get to where I wanted using the old MySQL shell.  Yes, the account to be used is identified by the native passwords and I had spelled the account name correctly. Then I double checked for fat-fingering on my part on the .env file where the connection details are stored. Then I did some searching and found someone else had stumbled onto the answer.What does not work:DATABASE_URL=mysql://account:password@127.0.0.1:3306/databasenameWhat does work:DATABASE_URL=mysql://account:password@localhost:3306/databasenameSo a simple s/127.0.0.1/hostname/ got things going.  I double checked the /etc/hosts file to make sure that alias was there (it was).From then on I was able to create a table with VARCHAR and JSON columns and go about my merry way.Update: An Oracle MySQL Engineer who works with the PHP connectors informed me that libmysql and all derived clients interpret "localhost" to mean "don't use TCP/ip, but Unix domain socket". And there was a kind post on the Doctrine mailing list informing me that the problems was upstream from Doctrine. Thanks to all who responded to solve this mystery for me.
  5. In the latest alpha release of React, a new concept was introduced, it is called Hooks. Hooks were introduced to React to solve many problems as explained in the introduction to Hooks session however, it primarily serves as an alternative for classes. With Hooks, we can create functional components that uses state and lifecycle methods. Related Reading: Getting Started with React Hooks Build a React To-Do App with React Hooks (No Class Components) Hooks are relatively new, as matter of fact, it is still a feature proposal. However, it is available for use at the moment if you'd like to play with it and have a closer look at what it offers. Hooks are currently available in React v16.7.0-alpha. It's important to note that there are no plans to ditch classes. React Hooks just give us another way to write React. And that's a good thing! Given that Hooks are still new, many developers are yet to grasp its concepts or understand how to apply it in their existing React applications or even in creating new React apps. In this post, we'll demonstrate 5 simple way to convert React Class Components to Functional Components using React Hooks. Class without state or lifecycle methods Let's start off with a simple React class that has neither state nor lifecycle components. Lets use a class that simply alerts a name when a user clicks a button: import React, { Component } from 'react'; class App extends Component { alertName = () => { alert('John Doe'); }; render() { return ( <div> <h3> This is a Class Component </h3> <button onClick={this.alertName}> Alert </button> </div> ); } } export default App; Here we have a usual React class, nothing new and nothing unusual. This class doesn't have state or any lifecycle method in it. It just alerts a name when a button is clicked. The functional equivalent of this class will look like this: import React from 'react'; function App() { const alertName = () => { alert(' John Doe '); }; return ( <div> <h3> This is a Functional Component </h3> <button onClick={alertName}> Alert </button> </div> ); }; export default App; Like the class component we had earlier, there's nothing new or unusual here. We haven't even used Hooks or anything new as of yet. This is because we've only considered an example where we have no need for state or lifecycle. But let's change that now and look at situations where we have a class based component with state and see how to convert it to a functional component using Hooks. Class with state Let's consider a situation where we have a global name variable that we can update within the app from a text input field. In React, we handle cases like this by defining the name variable in a state object and calling setState() when we have a new value to update the name variable with: import React, { Component } from 'react'; class App extends Component { constructor() { super(); this.state = { name: '' }; this.handleNameInput = this.handleNameInput.bind(this); } alertName = () => { alert(this.state.name); }; handleNameInput = e => { this.setState({ name: e.target.value }); }; render() { return ( <div> <h3> This is a Class Component </h3> <input type="text" onChange={this.handleNameInput} value={this.state.name} placeholder="Your name" /> <button onClick={this.alertName}> Alert </button> </div> ); } } export default App; When a user types a name in the input field and click the Alert button, it alerts the name we've defined in state. Once again this is a simple React concept, however, we can convert this entire class into a functional React component using Hooks like this: import React, { useState } from 'react'; function App() { const [name, setName] = useState('John Doe'); const alertName = () => { alert(name); }; const handleNameInput = e => { setName(e.target.value); }; return ( <div> <h3> This is a Functional Component </h3> <input type="text" onChange={handleNameInput} value={name} placeholder="Your name" /> <button onClick={alertName}> Alert </button> </div> ); }; export default App; Here, we introduced the useState Hook. It serves as a way of making use of state in React functional components. With theuseState() Hook, we've been able to use state in this functional component. It uses a similar syntax with destructuring assignment for arrays. Consider this line : const [name, setName] = useState("John Doe") Here, name is the equivalent of this.state in a normal class components while setName is the equivalent of this.setState . The last thing to understand while using the useState() Hook is that it takes an argument that serves as the initial value of the state. Simply put, the useState() argument is the initial value of the state. In our case, we set it to "John Doe" such that the initial state of the name in state is John Doe. This is primarily how to convert a class based React component with state to a functional component using Hooks. There are a lot more other useful ways of doing this as we'll see in subsequent examples. Class with multiple state properties It is one thing to easily convert one state property with useState however, the same approach doesn't quite apply when you have to deal with multiple state properties. Take for instance we had two or more input fields for userName, firstName and lastName then we would have a class based component with three state properties like this: import React, { Component } from 'react'; class App extends Component { constructor() { super(); this.state = { userName: '', firstName: '', lastName: '' }; this.handleUserNameInput = this.handleUserNameInput.bind(this); this.handleFirstNameInput = this.handleFirstNameInput.bind(this); this.handleLastNameInput = this.handleLastNameInput.bind(this); } logName = () => { // do whatever with the names... let's just log them here console.log(this.state.userName); console.log(this.state.firstName); console.log(this.state.lastName); }; handleUserNameInput = e => { this.setState({ userName: e.target.value }); }; handleFirstNameInput = e => { this.setState({ firstName: e.target.value }); }; handleLastNameInput = e => { this.setState({ lastName: e.target.value }); }; render() { return ( <div> <h3> This is a Class Component </h3> <input type="text" onChange={this.handleUserNameInput} value={this.state.userName} placeholder="Your username" /> <input type="text" onChange={this.handleFirstNameInput} value={this.state.firstName} placeholder="Your firstname" /> <input type="text" onChange={this.handleLastNameInput} value={this.state.lastName} placeholder="Your lastname" /> <button className="btn btn-large right" onClick={this.logName}> {' '} Log Names{' '} </button> </div> ); } } export default App; To convert this class to a functional component with Hooks, we'll have to take a somewhat unconventional route. Using the useState() Hook, the above example can be written as: import React, { useState } from 'react'; function App() { const [userName, setUsername] = useState(''); const [firstName, setFirstname] = useState(''); const [lastName, setLastname] = useState(''); const logName = () => { // do whatever with the names... let's just log them here console.log(userName); console.log(firstName); console.log(lastName); }; const handleUserNameInput = e => { setUsername(e.target.value); }; const handleFirstNameInput = e => { setFirstname(e.target.value); }; const handleLastNameInput = e => { setLastname(e.target.value); }; return ( <div> <h3> This is a functional Component </h3> <input type="text" onChange={handleUserNameInput} value={userName} placeholder="username..." /> <input type="text" onChange={handleFirstNameInput} value={firstName} placeholder="firstname..." /> <input type="text" onChange={handleLastNameInput} value={lastName} placeholder="lastname..." /> <button className="btn btn-large right" onClick={logName}> {' '} Log Names{' '} </button> </div> ); }; export default App; This demonstrates how we can convert a class based component with multiple state properties to a functional component using the useState() Hook. Here's the Codesandbox for this example. https://codesandbox.io/s/ypjynxx16x Class with state and componentDidMount Let's consider a class with only state and componentDidMount. To demonstrate such a class, let's create a scenario where we set an initial state for the three input fields and have them all update to a different set of values after 5 seconds. To achieve this, we'll have to declare an initial state value for the input fields and implement a componentDidMount() lifecycle method that will run after the initial render to update the state values. import React, { Component, useEffect } from 'react'; class App extends Component { constructor() { super(); this.state = { // initial state userName: 'JD', firstName: 'John', lastName: 'Doe' }; this.handleUserNameInput = this.handleUserNameInput.bind(this); this.handleFirstNameInput = this.handleFirstNameInput.bind(this); this.handleLastNameInput = this.handleLastNameInput.bind(this); } componentDidMount() { setInterval(() => { this.setState({ // update state userName: 'MJ', firstName: 'Mary', lastName: 'jane' }); }, 5000); } logName = () => { // do whatever with the names... let's just log them here console.log(this.state.userName); console.log(this.state.firstName); console.log(this.state.lastName); }; handleUserNameInput = e => { this.setState({ userName: e.target.value }); }; handleFirstNameInput = e => { this.setState({ firstName: e.target.value }); }; handleLastNameInput = e => { this.setState({ lastName: e.target.value }); }; render() { return ( <div> <h3> The text fields will update in 5 seconds </h3> <input type="text" onChange={this.handleUserNameInput} value={this.state.userName} placeholder="Your username" /> <input type="text" onChange={this.handleFirstNameInput} value={this.state.firstName} placeholder="Your firstname" /> <input type="text" onChange={this.handleLastNameInput} value={this.state.lastName} placeholder="Your lastname" /> <button className="btn btn-large right" onClick={this.logName}> {' '} Log Names{' '} </button> </div> ); } } export default App; When the app runs, the input fields will have the intial values we've defined in the state object. These values will then update to the values we've define inside the componentDidMount() method after 5 seconds. Now, let's convert this class to a functional component using the React useState and useEffect Hooks. import React, { useState, useEffect } from 'react'; function App() { const [userName, setUsername] = useState('JD'); const [firstName, setFirstname] = useState('John'); const [lastName, setLastname] = useState('Doe'); useEffect(() => { setInterval(() => { setUsername('MJ'); setFirstname('Mary'); setLastname('Jane'); }, 5000); }); const logName = () => { // do whatever with the names... console.log(this.state.userName); console.log(this.state.firstName); console.log(this.state.lastName); }; const handleUserNameInput = e => { setUsername({ userName: e.target.value }); }; const handleFirstNameInput = e => { setFirstname({ firstName: e.target.value }); }; const handleLastNameInput = e => { setLastname({ lastName: e.target.value }); }; return ( <div> <h3> The text fields will update in 5 seconds </h3> <input type="text" onChange={handleUserNameInput} value={userName} placeholder="Your username" /> <input type="text" onChange={handleFirstNameInput} value={firstName} placeholder="Your firstname" /> <input type="text" onChange={handleLastNameInput} value={lastName} placeholder="Your lastname" /> <button className="btn btn-large right" onClick={logName}> {' '} Log Names{' '} </button> </div> ); }; export default App; This component does exactly the same thing as the previous one. The only difference is that instead of using the conventional state object and componentDidMount() lifecycle method as we did in the class component, here, we used the useState and useEffect Hooks. Here's a Codesanbox for this example. https://codesandbox.io/s/jzoz2n97my Class with state, componentDidMount and componentDidUpdate Next, let's look at a React class with state and two lifecycle methods. So far you may have noticed that we've mostly been working with the useState Hook. In this example, let's pay more attention to the useEffect Hook. To best demonstrate how this works, let's update our code to dynamically update the <h3> header of the page. Currently the header says This is a Class Component. Now we'll define a componentDidMount() method to update the header to say Welcome to React Hooks after 3 seconds: import React, { Component } from 'react'; class App extends Component { constructor() { super(); this.state = { header: 'Welcome to React Hooks' }; // {... } } componentDidMount() { const header = document.querySelectorAll('#header')[0]; setTimeout(() => { header.innerHTML = this.state.header; }, 3000); } logName = () => { // do whatever with the names... }; // {... } render() { return ( <div> <h3 id="header"> This is a Class Component </h3> <input type="text" onChange={this.handleUserNameInput} value={this.state.userName} placeholder="Your username" /> <input type="text" onChange={this.handleFirstNameInput} value={this.state.firstName} placeholder="Your firstname" /> <input type="text" onChange={this.handleLastNameInput} value={this.state.lastName} placeholder="Your lastname" /> <button className="btn btn-large right" onClick={this.logName}> {' '} Log Names{' '} </button> </div> ); } } export default App; At this point, when the app runs, it starts with the initial header This is a Class Component and changes to Welcome to React Hooks after 3 seconds. This is the classic componentDidMount() behaviour since it runs after the render function is executed successfully. What if we want to dynamically update the header from another input field such that while we type, the header gets updated with the new text. To do that, we'll need to also implement the componentDidUpdate() lifecycle method like this: import React, { Component } from 'react'; class App extends Component { constructor() { super(); this.state = { header: 'Welcome to React Hooks' }; this.handleHeaderInput = this.handleHeaderInput.bind(this); // {... } } componentDidMount() { const header = document.querySelectorAll('#header')[0]; setTimeout(() => { header.innerHTML = this.state.header; }, 3000); } componentDidUpdate() { const node = document.querySelectorAll('#header')[0]; node.innerHTML = this.state.header; } logName = () => { // do whatever with the names... let's just log them here console.log(this.state.username); }; // {... } handleHeaderInput = e => { this.setState({ header: e.target.value }); }; render() { return ( <div> <h3 id="header"> This is a Class Component </h3> <input type="text" onChange={this.handleUserNameInput} value={this.state.userName} placeholder="Your username" /> <input type="text" onChange={this.handleFirstNameInput} value={this.state.firstName} placeholder="Your firstname" /> <input type="text" onChange={this.handleLastNameInput} value={this.state.lastName} placeholder="Your lastname" /> <button className="btn btn-large right" onClick={this.logName}> {' '} Log Names{' '} </button> <input type="text" onChange={this.handleHeaderInput} value={this.state.header} />{' '} </div> ); } } export default App; Here, we have state, componentDidMount() and componentDidUpdate() . So far when you run the app, the header updates to Welcome to React Hooks after 3 seconds as we defined in componentDidMount(). Then when you start typing in the header text input field, the <h3> text will update with the input text as defined in the componentDidUpdate() method. Now lets convert this class to a functional component with the useEffect() Hook. import React, { useState, useEffect } from 'react'; function App() { const [userName, setUsername] = useState(''); const [firstName, setFirstname] = useState(''); const [lastName, setLastname] = useState(''); const [header, setHeader] = useState('Welcome to React Hooks'); const logName = () => { // do whatever with the names... console.log(userName); }; useEffect(() => { const newheader = document.querySelectorAll('#header')[0]; setTimeout(() => { newheader.innerHTML = header; }, 3000); }); const handleUserNameInput = e => { setUsername(e.target.value); }; const handleFirstNameInput = e => { setFirstname(e.target.value); }; const handleLastNameInput = e => { setLastname(e.target.value); }; const handleHeaderInput = e => { setHeader(e.target.value); }; return ( <div> <h3 id="header"> This is a functional Component </h3> <input type="text" onChange={handleUserNameInput} value={userName} placeholder="username..." /> <input type="text" onChange={handleFirstNameInput} value={firstName} placeholder="firstname..." /> <input type="text" onChange={handleLastNameInput} value={lastName} placeholder="lastname..." /> <button className="btn btn-large right" onClick={logName}> {' '} Log Names{' '} </button> <input type="text" onChange={handleHeaderInput} value={header} /> </div> ); }; export default App; We've achieved exactly the same functionailty using the useEffect() Hook. It is even better or cleaner as some would say because here, we didn't have to write separate codes for componentDidMount() and componentDidUpdate() . With the useEffect() Hook, we are able to achieve both functions. This is because by default, useEffect() runs both after the initial render and after every subsequent update. Check out this example on this CodeSandbox. https://codesandbox.io/s/ork242q3y Convert PureComponent to React memo React PureComponent works in a similar manner to Component. The major difference between them is that React.Component doesn’t implement the shouldComponentUpdate() lifecycle method while React.PureComponent implements it. If your application's render() function renders the same result given the same props and state, you can use React.PureComponent for a performance boost in some cases. Related Reading: React 16.6: React.memo() for Functional Components Rendering Control The same thing applies to React.memo(). While the former refers to class based componentrs, React memo refers to functional components such that when your function component renders the same result given the same props, you can wrap it in a call to React.memo() to enhance performance. Using PureComponent and React.memo() gives React applications a considerable increase in performance as it reduces the number of render operations in the app. Here, we'll demonstrate how to convert a PureComponent class to a React memo component. To understand what exactly they both do, first, let's simulate a terrible situation where a component renders every 2 seconds wether or not there's a change value or state. We can quickly create this scenario like this: import React, { Component } from 'react'; const Unstable = props => { // monitor how many times this component is rendered console.log(' Rendered this component '); return ( <div> <p> {props.value}</p> </div> ); }; class App extends Component { state = { value: 1 }; componentDidMount() { setInterval(() => { this.setState(() => { return { value: 1 }; }); }, 2000); } render() { return ( <div> <Unstable value={this.state.value} /> </div> ); } } export default App; When you run the app and check the logs, you'll notice that it renders the component every 2 seconds without any change in state or props. As terrible as it is, this is exactly the scenario we wanted to create so we can show you how to fix it with both PureComponent and React.memo(). Most of the time, we only want to re-render a component when there's been a change in state or props. Now that we have experienced this awful situation, let's fix it with PureComponent such that the component only re-renders when there's a change in state or props. We do this by importing PureComponent and extending it like this: import React, { PureComponent } from 'react'; const Unstable = props => { console.log(' Rendered Unstable component '); return ( <div> <p> {props.value}</p> </div> ); }; class App extends PureComponent { state = { value: 1 }; componentDidMount() { setInterval(() => { this.setState(() => { return { value: 1 }; }); }, 2000); } render() { return ( <div> <Unstable value={this.state.value} /> </div> ); } } export default App; Now if you run the app again, you only get the initial render. Nothing else happens after that, why's that ? well, instead of class App extends Component{} now we have class App extends PureComponent{} This solves our problem of re-rendering components, without respect to the current state. If however, we change this method: componentDidMount() { setInterval(() => { this.setState(() => { return { value: 1 }; }); }, 2000); } To: componentDidMount() { setInterval(() => { this.setState(() => { return { value: Math.random() }; }); }, 2000); } The component will re-render each time the value updates to the next random number. So, PureComponent makes it possible to only re-render components when there's been a change in state or props. Now let's see how we can use React.memo() to achieve the same fix. To do this with React memo, simply wrap the component with React.memo() Like this: import React, { Component } from 'react'; const Unstable = React.memo(props => { console.log(' Rendered this component '); return ( <div> <p> {props.value}</p> </div> ); }); class App extends Component { state = { value: 1 }; componentDidMount() { setInterval(() => { this.setState(() => { return { value: 1 }; }); }, 2000); } render() { return ( <div> <Unstable value={this.state.value} /> </div> ); } } export default App; This achieves the same result as PureComponent did. Hence, the component only renders after the initial render and doesn't re-render again until there's a change in state or props. Here's the Codesandbox for this example. https://codesandbox.io/s/100zmv7ljj Conclusion In this post we have demonstrated a few ways to covert an existing class based component to a functional component using React Hooks. We have also looked at a special case of converting a React PureComponent class to React.memo(). It may be obvious but i still feel the need to mention that in order to use Hooks in your applications, you'll need to update your React to the supported version: "react": "^16.7.0-alpha", "react-dom": "^16.7.0-alpha", React Hooks is still a feature proposal, however, we are hoping that it will be part of the next stable release as it makes it possible for us to eat our cake (use state in function components) and still have it back (retain the simplicity of writing functional components).