<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Jeff</title>
    <description>The latest articles on Forem by Jeff (@jeffersonlicet).</description>
    <link>https://forem.com/jeffersonlicet</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F264288%2Fa25b019f-9c67-42d5-9301-085090c2df63.jpeg</url>
      <title>Forem: Jeff</title>
      <link>https://forem.com/jeffersonlicet</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/jeffersonlicet"/>
    <language>en</language>
    <item>
      <title>Text classification using Machine Learning - Tensorflow - AI</title>
      <dc:creator>Jeff</dc:creator>
      <pubDate>Tue, 27 Jul 2021 01:23:03 +0000</pubDate>
      <link>https://forem.com/jeffersonlicet/text-classification-using-machine-learning-tensorflow-ai-2pf5</link>
      <guid>https://forem.com/jeffersonlicet/text-classification-using-machine-learning-tensorflow-ai-2pf5</guid>
      <description>&lt;h2&gt;
  
  
  Hey 👋
&lt;/h2&gt;

&lt;p&gt;I want to share my experience participating in the #MeliDataChallenge 2019. (Mercadolibre.com challenge)&lt;/p&gt;

&lt;p&gt;I'm not an expert. I like to participate in contests like this to learn about Machine Learning and AI with real world applications, soon I will publish my experience and my solution for the Despegar challenge (Images classification).&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The challenge&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The challenge was very interesting, classify e-commerce products using only its titles.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The prize&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;First and second place will receive tickets to KHIPU. From 3 to 5 place an Intel Movidius.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Il7kG0ih--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/RifuOIr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Il7kG0ih--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://i.imgur.com/RifuOIr.png" alt="Prize"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The result&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;I managed to be in the top 20 with a score of &lt;strong&gt;0.8954/1&lt;/strong&gt;, there were more of 150 participants, the competition was hard and exciting. Of course, I learned a lot of new things.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;POSITION&lt;/th&gt;
&lt;th&gt;NAME&lt;/th&gt;
&lt;th&gt;SCORE&lt;/th&gt;
&lt;th&gt;ENTRIES&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;jefferson1100001&lt;/td&gt;
&lt;td&gt;0.895456136076574&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Let's explain my approach&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The first thing I did was to take a look of the data, Mercadolibre provided two files, train.csv and test.csv.  This is how train.csv looks like:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;TITLE&lt;/th&gt;
&lt;th&gt;LABEL_QUALITY&lt;/th&gt;
&lt;th&gt;LANGUAGE&lt;/th&gt;
&lt;th&gt;CATEGORY&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Hidrolavadora Lavor One 120 Bar 1700w Bomba A...&lt;/td&gt;
&lt;td&gt;unreliable&lt;/td&gt;
&lt;td&gt;spanish&lt;/td&gt;
&lt;td&gt;ELECTRIC_PRESSURE_WASHERS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Placa De Sonido - Behringer Umc22&lt;/td&gt;
&lt;td&gt;unreliable&lt;/td&gt;
&lt;td&gt;spanish&lt;/td&gt;
&lt;td&gt;SOUND_CARDS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Maquina De Lavar Electrolux 12 Kilos&lt;/td&gt;
&lt;td&gt;unreliable&lt;/td&gt;
&lt;td&gt;portuguese&lt;/td&gt;
&lt;td&gt;WASHING_MACHINES&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;There are 12,644,401 valid rows, the dataset is unbalanced and some categories are present in just one language.&lt;/p&gt;

&lt;h2&gt;
  
  
  Data preprocessing
&lt;/h2&gt;

&lt;p&gt;Here I will describe my preprocess routines without code.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Remove tildes&lt;br&gt;
Spanish and Portuguese words have tildes, like teléfono. This step mutates the word to telefono.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Remove word separators&lt;br&gt;
Some titles have dash, dots and other punctuation marks without a space between them, for example kit.ruedas.moto.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'm replacing each one of this marks with a space.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;+ , . ( ) : [ ] { } _ /&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Remove other punctuation marks and numbers&lt;br&gt;
I've removed any other punctuation mark and numbers, but the number must be surrounded by a word boundary.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tokenize the title&lt;br&gt;
I applied the WordPunctTokenizer provided by NLTK to split each title into words.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Remove stop words&lt;br&gt;
On the resulting array of words I discarded stop words like: "un", "unas", "unos"...&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Stem each token&lt;br&gt;
I used the SnowballStemmer provided by NLTK. Stemming is the process of reducing inflected (or sometimes derived) words to their word stem. For example: Cámara is transformed to "cam".&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Preprocessing result
&lt;/h2&gt;

&lt;p&gt;Let's take a look of the titles titles before and after preprocessing:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;BEFORE&lt;/th&gt;
&lt;th&gt;AFTER PREPROCESSING&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Placa De Sonido - Behringer Umc22&lt;/td&gt;
&lt;td&gt;plac son behring umc22&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Oportunidad! Notebook Dell I3 - 4gb Ddr4 - Hd 1tb - Win 10&lt;/td&gt;
&lt;td&gt;oportun notebook dell i3 4gb ddr4 hd 1tb win&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cámara Instantánea Fujifilm Instax Mini 9 - Azul Cobalto&lt;/td&gt;
&lt;td&gt;cam instantane fujifilm instax mini azul cobalt&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;I saved a copy of train.csv with all the titles preprocessed, a list with all the posible categories and a list with all labels.&lt;/p&gt;

&lt;h2&gt;
  
  
  The dictionary:
&lt;/h2&gt;

&lt;p&gt;Iterating over all the preprocessed titles and with the help of a Counter I had created a dictionary containing words only if their frequency is &amp;gt;= 2. It means that the word must occur at least two times in some title.&lt;/p&gt;

&lt;p&gt;The dictionary looks like this&lt;/p&gt;

&lt;p&gt;&lt;code&gt;{'kit': 785233, 'original': 469537, 'pret': 232647, 'led': 220194, ...}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;There are 1,251,659 unique tokens, after filtering them the dictionary has 513,307 posible words.&lt;/p&gt;

&lt;p&gt;Let's transform the preprocessed titles to numbers&lt;br&gt;
In this step I used the dictionary to transform each title into an array of numbers. It's very simple, for each word in the title, replace it with the corresponding index of the word in the dictionary plus 1. (0 is reserved).&lt;/p&gt;

&lt;p&gt;A preprocessed title like this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;['porton', 'chap', 'hoj', 'mtr', 'marc']&lt;/code&gt;&lt;br&gt;
Becomes:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;[120, 121, 122, 123, 124]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The max word sequence has len 27, if the transformed title has len less than 27, we pad it with zeros so each title has the same length.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;[120, 121, 122, 123, 124, 0, 0, 0, 0, 0, 0, 0, ....]&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Now it's time for Machine Learning
&lt;/h3&gt;

&lt;p&gt;I've used Tensorflow + Keras, the model has the following architecture:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fNwO0qnt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://jeffersonlicet.com/content/images/2019/10/arch.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fNwO0qnt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://jeffersonlicet.com/content/images/2019/10/arch.png" alt="Architecture"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Key points you must know
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Seed random numbers, so you can get reproducible results.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use stratified samples when splitting test and train&lt;br&gt;
It means that each set must have the same proportion of classes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Take 1% for testing&lt;br&gt;
The dataset is relative big, 1% seems to represent a good number of features of the dataset for being validated.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use class_weights&lt;br&gt;
Due to the imbalanced nature of the dataset, class_weights increased the BACC of the model.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Explore the data locally&lt;br&gt;
And maybe preprocess locally but use multiprocessing&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use Colab or Kaggle&lt;br&gt;
To take adventage of the GPU and train faster&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Training:
&lt;/h2&gt;

&lt;p&gt;After 18 epochs the model seems to achieve good results before start to overfitting. The balanced accuracy was: 0.86774697&lt;/p&gt;

&lt;p&gt;Testing a new title:&lt;br&gt;
If we feed the model with complete new data, for example:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;"Buzo Harry Potter Lentes Cicatriz Hogwarts Hoodie"&lt;/code&gt;&lt;br&gt;
It will predict:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;SWEATSHIRTS_AND_HOODIES&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The alternative attempt:
&lt;/h2&gt;

&lt;p&gt;I also created a small model with just 1400 categories representing the reliable subset.  The the goal was to feed that model with the unreliable subset in order to detect if the unreliable categories were in the wrong categories, but this adds complexity and I'd to optimize two models instead of just one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next steps:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;You can use the label_quality somehow to increase model ACC.&lt;/li&gt;
&lt;li&gt;Use confusion matrix or any performance measurement to detect where does our model perform worst.&lt;/li&gt;
&lt;li&gt;Use a complex architecture or CNN&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Github with all the code:
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/jeffersonlicet/ml-titles-classification"&gt;https://github.com/jeffersonlicet/ml-titles-classification&lt;/a&gt;&lt;/p&gt;

</description>
      <category>tensorflow</category>
      <category>machinelearning</category>
      <category>nlp</category>
      <category>python</category>
    </item>
    <item>
      <title>Hero animations in React with react-motion-layout</title>
      <dc:creator>Jeff</dc:creator>
      <pubDate>Fri, 27 Mar 2020 00:52:23 +0000</pubDate>
      <link>https://forem.com/jeffersonlicet/hero-animations-in-react-with-react-motion-layout-kfh</link>
      <guid>https://forem.com/jeffersonlicet/hero-animations-in-react-with-react-motion-layout-kfh</guid>
      <description>&lt;p&gt;Hello Devs.&lt;/p&gt;

&lt;p&gt;A couple of days ago I published my first React package and I want to show you how to use it.&lt;/p&gt;

&lt;h2&gt;
  
  
  React-Motion-Layout
&lt;/h2&gt;

&lt;p&gt;This library helps you animate components from two different React trees. In other words, to create Hero Animations. It's compatible with moderns browsers and uses the Element.animate() Web API.&lt;/p&gt;

&lt;p&gt;Let's build one of my favorite examples, a photo gallery.&lt;/p&gt;

&lt;h4&gt;
  
  
  This is the final result
&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;Click on any photo to see it in action.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/b6gkm"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Looks beautiful right? Let's take a look at how simple is to recreate this example.&lt;/p&gt;

&lt;h3&gt;
  
  
  1 - Create placeholder photos
&lt;/h3&gt;

&lt;p&gt;Thanks to Unsplash for those amazing photos.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// PhotosDB.js&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;photo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://images.unsplash.com/photo-1474313438662-85ce389c174a?ixlib=rb-1.2.1&amp;amp;ixid=eyJhcHBfaWQiOjEyMDd9&amp;amp;auto=format&amp;amp;fit=crop&amp;amp;w=500&amp;amp;q=50&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;photo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://images.unsplash.com/photo-1521170665346-3f21e2291d8b?ixlib=rb-1.2.1&amp;amp;ixid=eyJhcHBfaWQiOjEyMDd9&amp;amp;auto=format&amp;amp;fit=crop&amp;amp;w=500&amp;amp;q=50&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;photo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://images.unsplash.com/photo-1520512202623-51c5c53957df?ixlib=rb-1.2.1&amp;amp;ixid=eyJhcHBfaWQiOjEyMDd9&amp;amp;auto=format&amp;amp;fit=crop&amp;amp;w=500&amp;amp;q=50&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2 - Let's wrap our app with MotionLayoutProvider
&lt;/h3&gt;

&lt;p&gt;Motion Layout Provider is responsible for providing the state management.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// App.js&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Router&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MotionLayoutProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Switch&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Route&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/photo/:photoId"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Photo&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Route&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Route&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Photos&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Route&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Switch&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;MotionLayoutProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Router&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3 - Create The Photos Component
&lt;/h3&gt;

&lt;p&gt;Since this is an individual screen, we'll wrap it using MotionScreen to clean registered elements when abandoning this screen.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;MotionScreen&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-motion-layout&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;Photos&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MotionScreen&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"flex flex-wrap"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
         &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;PhotosDB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
           &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ItemComponent&lt;/span&gt; &lt;span class="na"&gt;item&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
         &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;MotionScreen&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4 - The single photo item
&lt;/h3&gt;

&lt;p&gt;Each item will be wrapped with a  &lt;strong&gt;MotionScene&lt;/strong&gt;. A  &lt;strong&gt;MotionScene&lt;/strong&gt;  is a component that contains  &lt;strong&gt;SharedElements&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SharedElements&lt;/strong&gt;  are the components that we will animate. They must have an unique key called  &lt;em&gt;animationKey&lt;/em&gt;, we use that key to find a matching SharedElement when changing the views.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;MotionScene&lt;/strong&gt;  accepts an onClick property, in this case we are using the  &lt;strong&gt;withTransition&lt;/strong&gt;  hook, that will trigger the animation and then will change the route using the history hook provided by react-router-dom.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useMotion&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;MotionScene&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;SharedElement&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-motion-layout&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// PhotoItem.js&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;ItemComponent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;history&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useHistory&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;withTransition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useMotion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`photo-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;callback&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useCallback&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;history&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/photo/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nx"&gt;history&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;id&lt;/span&gt;
  &lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MotionScene&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`photo-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;withTransition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"p-4 cursor-pointer hover:bg-gray-100"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SharedElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Image&lt;/span&gt;
          &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"w-64"&lt;/span&gt;
          &lt;span class="na"&gt;alt&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;
          &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;photo&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="na"&gt;animationKey&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"image"&lt;/span&gt;
        &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;MotionScene&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5 - The individual photo view
&lt;/h3&gt;

&lt;p&gt;The Story View is wrapped by a MotionScreen since it represents a single screen. And of course, it could contain more than a single Scene.&lt;/p&gt;

&lt;p&gt;Since it's just one scene, we will wrap it with MotionScene as well, when navigating, those scenes will match and the Package with look for the declared SharedComponents and match them using its keys. then, it will perform the animation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useParams&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-router-dom&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;PhotosDB&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./PhotosDB&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;MotionScene&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;MotionScreen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;SharedElement&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-motion-layout&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;Photo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;photoId&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useParams&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;PhotosDB&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;photoId&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MotionScreen&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MotionScene&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`photo-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;photoId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"flex flex-col p-8"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SharedElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Image&lt;/span&gt;
            &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"w-64"&lt;/span&gt;
            &lt;span class="na"&gt;alt&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;
            &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;photo&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="na"&gt;animationKey&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"image"&lt;/span&gt;
          &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;MotionScene&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;MotionScreen&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  And that's it
&lt;/h2&gt;

&lt;p&gt;Now when you click on any item of the gallery it should animate using the shared components we'd just defined.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://motion-layout.azurewebsites.net/"&gt;Motion Layout Docs&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/jeffersonlicet/react-motion-layout"&gt;Github&lt;/a&gt;&lt;br&gt;
&lt;a href="https://codesandbox.io/s/chat-example-dyyy1"&gt;Example using Text&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Thanks.
&lt;/h3&gt;

</description>
      <category>transition</category>
      <category>react</category>
      <category>hero</category>
    </item>
  </channel>
</rss>
