{"id":28352,"date":"2022-03-24T19:41:59","date_gmt":"2022-03-24T19:41:59","guid":{"rendered":"http:\/\/React-Selfie-App-with-Cloudinary"},"modified":"2022-03-24T19:41:59","modified_gmt":"2022-03-24T19:41:59","slug":"react-selfie-app-with-cloudinary","status":"publish","type":"post","link":"https:\/\/cloudinary.com\/blog\/guest_post\/react-selfie-app-with-cloudinary\/","title":{"rendered":"React Selfie App with Cloudinary"},"content":{"rendered":"<div class=\"wp-block-cloudinary-markdown \"><p>In this article, we\u2019ll learn how to build an application that allows us to take pictures using a webcam. In other words, we will build a selfie application using React.js and then use the rich image transformation features provided by Cloudinary to apply unique special effects to our captured images. This should be a lot of fun! Let\u2019s get started.<\/p>\n<p>This article assumes you are familiar with the basics of JavaScript and React.<\/p>\n<p>Here is a link to the demo on <a href=\"https:\/\/codesandbox.io\/s\/react-selfie-filter-app-with-cloudinary-bub96?file=\/src\/App.js\">CodeSandbox<\/a> and the full source code here on <a href=\"https:\/\/github.com\/ifeoma-imoh\/React-selfie-filter-app\">GitHub<\/a>.<\/p>\n<\/div>\n  \n  <div class=\"wp-block-cloudinary-code-sandbox \">\n    <iframe\n      src=\"https:\/\/codesandbox.io\/embed\/react-selfie-filter-app-with-cloudinary-bub96?file=%2Fsrc%2FApp.js&amp;theme=dark&amp;codemirror=1&amp;highlights=&amp;editorsize=50&amp;fontsize=14&amp;expanddevtools=0&amp;hidedevtools=0&amp;eslint=0&amp;forcerefresh=0&amp;hidenavigation=0&amp;initialpath=%2F&amp;module=&amp;moduleview=0&amp;previewwindow=&amp;view=&amp;runonclick=1\"\n      height=\"500\"\n      style=\"width: 100%;\"\n      title=\"react-selfie-filter-app-with-cloudinary\"\n      loading=\"lazy\"\n      allow=\"accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking\"\n      sandbox=\"allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts\"\n    ><\/iframe>\n  <\/div>\n\n  <div class=\"wp-block-cloudinary-markdown \"><h2>Setting up Cloudinary<\/h2>\n<p>We will be using Cloudinary to take advantage of the SDKs, so you need to <a href=\"https:\/\/cloudinary.com\/users\/register\/free\">create an account<\/a> if you do not have one already.<\/p>\n<p>Log in after creating your account, and on your dashboard page, you should see all your credentials (cloud name, etc.) Before we can apply transformations to an image, the image needs to be uploaded to Cloudinary servers. Since our uploads will be done from our client-side application, we need to define an <a href=\"https:\/\/cloudinary.com\/documentation\/upload_presets\">upload preset<\/a>. Upload presets can either be signed or unsigned and we would be using the unsigned presets.<\/p>\n<p>If you don\u2019t have an unsigned preset already, you can create one as follows:<\/p>\n<ul>\n<li>Go to your Cloudinary dashboard and click on the <strong>settings icon<\/strong>.<\/li>\n<li>Select the <strong>Upload<\/strong> tab and scroll down to the <strong>Upload presets<\/strong> section.<\/li>\n<li>Click the <strong>Add upload preset<\/strong> link.<\/li>\n<li>In the form displayed, add a <strong>name<\/strong> for your upload preset and set the <strong>Signing mode<\/strong> to <strong>unsigned<\/strong>, and click the <strong>Save<\/strong> button.<\/li>\n<\/ul>\n<blockquote>\n<p>Take note of the preset name because it will be used later to upload captured images.<\/p>\n<\/blockquote>\n<h2>Environment Setup<\/h2>\n<p>Open your terminal and run the following command to bootstrap a React app in a folder called <code>selfie-app<\/code>.<\/p>\n<pre class=\"js-syntax-highlighted\"><span><code class=\"hljs shcb-wrap-lines\">    npx create-react-app selfie-app\n<\/code><\/span><\/pre>\n<p>The next step is to install the dependencies that we will need in this project. Run the following command to install them.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css shcb-wrap-lines\">    <span class=\"hljs-selector-tag\">npm<\/span> <span class=\"hljs-selector-tag\">install<\/span> <span class=\"hljs-selector-tag\">--save<\/span> <span class=\"hljs-keyword\">@cloudinary<\/span>\/url-gen axios react-webcam\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>The command above installs the Cloudinary SDKs that we will use in our application. We will be using the <code>@Cloudinary\/url-gen<\/code> package to configure Cloudinary, build image URLs and apply transformations (filters and visual enhancements). Axios will be our HTTP client for uploading images, and react-webcam will be used to access the user\u2019s camera and capture images.<\/p>\n<p>A bird\u2019s-eye view of all the moving parts that make up our app is provided below. Include the following code in your App.js file.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">    <span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-string\">\".\/App.css\"<\/span>;\n    <span class=\"hljs-keyword\">import<\/span> { useRef, useState } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"react\"<\/span>;\n    <span class=\"hljs-keyword\">import<\/span> Webcam <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"react-webcam\"<\/span>;\n    <span class=\"hljs-keyword\">import<\/span> axios <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"axios\"<\/span>;\n    <span class=\"hljs-keyword\">import<\/span> { Cloudinary } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"@cloudinary\/url-gen\"<\/span>;\n    <span class=\"hljs-keyword\">import<\/span> { Effect } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"@cloudinary\/url-gen\/actions\/effect\"<\/span>;\n\n    <span class=\"hljs-comment\">\/\/Add your cloud name<\/span>\n    <span class=\"hljs-keyword\">let<\/span> cloudName = <span class=\"hljs-string\">\"ADD-YOUR-CLOUD-NAME-HERE\"<\/span>;\n    <span class=\"hljs-keyword\">const<\/span> cld = <span class=\"hljs-keyword\">new<\/span> Cloudinary({\n        <span class=\"hljs-attr\">cloud<\/span>: {\n            cloudName,\n        },\n    });\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">applyFilter<\/span>(<span class=\"hljs-params\">filter, image<\/span>) <\/span>{\n      <span class=\"hljs-comment\">\/\/ this will be used to apply filters<\/span>\n    }\n    <span class=\"hljs-keyword\">const<\/span> filters = &#91;\n    <span class=\"hljs-comment\">\/\/ strings representing a filter<\/span>\n    ];\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">ImagePreviewer<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n     <span class=\"hljs-comment\">\/\/ this will be used to display our image<\/span>\n    }\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">FilterItem<\/span>(<span class=\"hljs-params\">{ imgId, setPrevURL, filterName }<\/span>) <\/span>{\n    <span class=\"hljs-comment\">\/\/this will be used to apply a filter<\/span>\n    }\n    <span class=\"hljs-keyword\">const<\/span> App = <span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {\n       <span class=\"hljs-comment\">\/\/ this will hold our camera stream, imagePreviewer and filter components <\/span>\n    };\n    <span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> App;\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>First, we\u2019re importing react hooks, Axios, and some components from the Cloudinary SDK. We then create an instance of the Cloudinary class and initialized it with our cloud name. The Cloudinary instance will be used to build the delivery URLs for our assets.<\/p>\n<p>Next, we define a function called <code>applyFilter<\/code>, which accepts a filter and an image to which the desired filter will be applied. We also define an array that will hold strings each representing the different filters (e.g., sepia, greyscale) that will be applied to our images.<\/p>\n<p>Finally, we defined some components we\u2019ll need and exported our App component. Over the following sections, we will be visiting each function as the need arises to update their logic as we build our application.<\/p>\n<h2>Setting up Camera<\/h2>\n<p>In your <code>App.js<\/code> file, update your App component with the following:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">    <span class=\"hljs-keyword\">const<\/span> App = <span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {\n      <span class=\"hljs-keyword\">const<\/span> constraints = {\n        <span class=\"hljs-attr\">width<\/span>: <span class=\"hljs-number\">700<\/span>,\n        <span class=\"hljs-attr\">height<\/span>: <span class=\"hljs-number\">550<\/span>,\n        <span class=\"hljs-attr\">facingMode<\/span>: <span class=\"hljs-string\">\"user\"<\/span>,\n        <span class=\"hljs-attr\">aspectRatio<\/span>: <span class=\"hljs-number\">9<\/span> \/ <span class=\"hljs-number\">16<\/span>,\n      };\n      <span class=\"hljs-keyword\">const<\/span> camRef = useRef();\n      <span class=\"hljs-keyword\">const<\/span> &#91;loading, setLoading] = useState(<span class=\"hljs-literal\">false<\/span>);\n      <span class=\"hljs-keyword\">return<\/span> (\n        <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">section<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"main\"<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">article<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"media_box\"<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Webcam<\/span>\n              \/\/ <span class=\"hljs-attr\">this<\/span> <span class=\"hljs-attr\">will<\/span> <span class=\"hljs-attr\">be<\/span> <span class=\"hljs-attr\">used<\/span> <span class=\"hljs-attr\">internally<\/span> <span class=\"hljs-attr\">to<\/span> <span class=\"hljs-attr\">bind<\/span> <span class=\"hljs-attr\">some<\/span> <span class=\"hljs-attr\">useful<\/span> <span class=\"hljs-attr\">methods<\/span> <span class=\"hljs-attr\">to<\/span> <span class=\"hljs-attr\">the<\/span> <span class=\"hljs-attr\">ref<\/span> <span class=\"hljs-attr\">variable.<\/span>\n              <span class=\"hljs-attr\">ref<\/span>=<span class=\"hljs-string\">{camRef}<\/span>\n              <span class=\"hljs-attr\">videoConstraints<\/span>=<span class=\"hljs-string\">{constraints}<\/span>\n              \/\/<span class=\"hljs-attr\">this<\/span> <span class=\"hljs-attr\">specifies<\/span> <span class=\"hljs-attr\">the<\/span> <span class=\"hljs-attr\">file<\/span> <span class=\"hljs-attr\">format<\/span> <span class=\"hljs-attr\">we<\/span> <span class=\"hljs-attr\">want<\/span> <span class=\"hljs-attr\">for<\/span> <span class=\"hljs-attr\">the<\/span> <span class=\"hljs-attr\">captured<\/span>\n              <span class=\"hljs-attr\">screenshotFormat<\/span>=<span class=\"hljs-string\">\"image\/jpeg\"<\/span>\n            \/&gt;<\/span>\n            {\/* this button will be used to capture the image*\/}\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">button<\/span>\n              <span class=\"hljs-attr\">disabled<\/span>=<span class=\"hljs-string\">{loading}<\/span>\n              <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"capture_btn\"<\/span>\n            &gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">button<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">article<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">section<\/span>&gt;<\/span><\/span>\n      );\n    };\n    <span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> App;\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>In the code above, we created an object that defines the media constraints of the video recording before an image is captured. We also defined a reference that will give us access to our web camera using the <code>useRef<\/code> hook and a state variable to toggle between loading states when uploading an image.<\/p>\n<p>Finally, we returned the Webcam component and a button that is disabled when loading.<\/p>\n<p>If you open your browser on <code>localhost:3000<\/code>, should see this:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/res.cloudinary.com\/jesse-thisdot\/image\/upload\/c_limit,w_2000\/f_auto\/q_auto\/v1633967184\/e-61325f69b4ddf000699b0fe3\/rynwksgq5dknqgetgdip.png\" alt=\"\" loading=\"lazy\" class=\"c-transformed-asset\"  width=\"1600\" height=\"548\"\/><\/p>\n<p>Under the hood, the <code>Webcam<\/code> component requests permission to access media devices as defined in the audio and video constraints. In this case, it requests access to the camera. When authorized, it receives a media stream object, creates a video element, and uses the media stream object as its source.<\/p>\n<h2>Capture, Upload, Delete and Display Features<\/h2>\n<p>At this point, we can\u2019t do much with what we have. Let\u2019s add some functionalities to be able to capture and upload an image.<\/p>\n<p>Add the following to your <code>App<\/code> component.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">    <span class=\"hljs-keyword\">const<\/span> App = <span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {\n      <span class=\"hljs-keyword\">const<\/span> constraints = {\n        <span class=\"hljs-attr\">width<\/span>: <span class=\"hljs-number\">700<\/span>,\n        <span class=\"hljs-attr\">height<\/span>: <span class=\"hljs-number\">550<\/span>,\n        <span class=\"hljs-attr\">facingMode<\/span>: <span class=\"hljs-string\">\"user\"<\/span>,\n        <span class=\"hljs-attr\">aspectRatio<\/span>: <span class=\"hljs-number\">9<\/span> \/ <span class=\"hljs-number\">16<\/span>,\n      };\n      <span class=\"hljs-keyword\">const<\/span> camRef = useRef();\n      <span class=\"hljs-keyword\">const<\/span> &#91;loading, setLoading] = useState(<span class=\"hljs-literal\">false<\/span>);\n      <span class=\"hljs-keyword\">const<\/span> &#91;id, setId] = useState(<span class=\"hljs-string\">\"\"<\/span>);\n      <span class=\"hljs-keyword\">const<\/span> &#91;prevURL, setPrevURL] = useState(<span class=\"hljs-string\">\"\"<\/span>);\n      <span class=\"hljs-keyword\">const<\/span> captureAndUpload = <span class=\"hljs-keyword\">async<\/span> () =&gt; {\n        <span class=\"hljs-comment\">\/\/ get screenshot<\/span>\n        <span class=\"hljs-keyword\">const<\/span> data = camRef.current.getScreenshot();\n        <span class=\"hljs-comment\">\/\/ upload to cloudinary and get public_id<\/span>\n        <span class=\"hljs-keyword\">try<\/span> {\n          setLoading(<span class=\"hljs-literal\">true<\/span>);\n          <span class=\"hljs-keyword\">const<\/span> imageData = <span class=\"hljs-keyword\">new<\/span> FormData();\n          imageData.append(<span class=\"hljs-string\">\"file\"<\/span>, data);\n\n         <span class=\"hljs-comment\">\/\/ Add your upload preset here<\/span>\n          imageData.append(<span class=\"hljs-string\">\"upload_preset\"<\/span>, <span class=\"hljs-string\">\"ADD-YOUR-UPLOAD-PRESET-HERE\"<\/span>);\n          <span class=\"hljs-keyword\">const<\/span> res = <span class=\"hljs-keyword\">await<\/span> axios.post(\n            <span class=\"hljs-string\">` https:\/\/api.cloudinary.com\/v1_1\/<span class=\"hljs-subst\">${cloudName}<\/span>\/image\/upload`<\/span>,\n            imageData\n          );\n          <span class=\"hljs-keyword\">const<\/span> imageDetails = res.data;\n          setId(imageDetails.public_id);\n          setPrevURL(imageDetails.url);\n        } <span class=\"hljs-keyword\">catch<\/span> (error) {\n          <span class=\"hljs-built_in\">console<\/span>.log(error);\n        } <span class=\"hljs-keyword\">finally<\/span> {\n          setLoading(<span class=\"hljs-literal\">false<\/span>);\n        }\n        <span class=\"hljs-comment\">\/\/set publicID<\/span>\n      };\n      <span class=\"hljs-keyword\">const<\/span> deleteImage = <span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {\n        setPrevURL(<span class=\"hljs-string\">\"\"<\/span>);\n        setId(<span class=\"hljs-string\">\"\"<\/span>);\n      };\n      <span class=\"hljs-keyword\">return<\/span> (\n        <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">section<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"main\"<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">article<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"media_box\"<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Webcam<\/span>\n              <span class=\"hljs-attr\">ref<\/span>=<span class=\"hljs-string\">{camRef}<\/span>\n              <span class=\"hljs-attr\">videoConstraints<\/span>=<span class=\"hljs-string\">{constraints}<\/span>\n              <span class=\"hljs-attr\">screenshotFormat<\/span>=<span class=\"hljs-string\">\"image\/jpeg\"<\/span>\n            \/&gt;<\/span>\n            {\/* this button will be used to capture the image*\/}\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">button<\/span>\n              <span class=\"hljs-attr\">disabled<\/span>=<span class=\"hljs-string\">{loading}<\/span>\n              <span class=\"hljs-attr\">onClick<\/span>=<span class=\"hljs-string\">{captureAndUpload}<\/span>\n              <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"capture_btn\"<\/span>\n            &gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">button<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">article<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">section<\/span>&gt;<\/span><\/span>\n      );\n    };\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>In the code above, we added two state variables called <code>id<\/code> and <code>previewUrl<\/code>.  They will hold the <code>public_id<\/code> and the delivery URL, respectively. Before applying transformations to our media assets, we need to upload them to our Cloudinary account first. Each uploaded asset will be given a unique public ID that will be used to reference it and build its delivery URL.<\/p>\n<p>We also defined <code>CaptureAndUpload<\/code> and <code>deleteImage<\/code>, which updates and clears our ID and previewURL variables. As the name implies, the function <code>CaptureAndUpload<\/code> gets the image data from the call to the <code>getScreenShot<\/code> function and saves it in a variable. We then toggle our loading state to prevent a user from clicking the button to capture another image during the upload process.<\/p>\n<p>Before uploading, we construct our request body using a FormData object and specify key-value pairs that signify the following:<\/p>\n<ul>\n<li>File: this is the file we want to upload. Cloudinary supports different <a href=\"https:\/\/cloudinary.com\/documentation\/upload_images#public_id\">file source options<\/a>, and in this case, we are using the base64 encoded string representation of our image from the call to the <code>getScreenshot<\/code> function.<\/li>\n<li>upload_preset: this string represents the unsigned upload preset we created earlier.<\/li>\n<\/ul>\n<blockquote>\n<p>Since we are doing unsigned uploads, the file and upload_preset parameters are <strong>mandatory<\/strong> to see a complete list of other options; check here.<\/p>\n<\/blockquote>\n<p>Next, we hit the Cloudinary upload endpoint and pass our request body as an input. If everything goes fine, we get an <a href=\"https:\/\/cloudinary.com\/documentation\/upload_images#upload_response\">upload response<\/a> object which contains information about the uploaded asset. We then take the public_ID and URL and store them in our <code>id<\/code> and <code>previewURL<\/code> variables. If we get an error, we print it to the console.<\/p>\n<p>We created a <code>deleteImage<\/code> function that clears the content of our state variables in our React application, but the image will still be present on our Cloudinary account.<\/p>\n<p>Now we can take pictures and upload them to Cloudinary, but we also need to display the image. In our <code>App.js<\/code> file, let\u2019s update our <code>ImagePreviewer<\/code> component.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">    <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">ImagePreviewer<\/span>(<span class=\"hljs-params\">{ url, deleteImage }<\/span>) <\/span>{\n        <span class=\"hljs-keyword\">return<\/span> url ? (\n            <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"img_box\"<\/span>&gt;<\/span>\n                <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">img<\/span> <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">{url}<\/span> <span class=\"hljs-attr\">alt<\/span>=<span class=\"hljs-string\">\"my_image\"<\/span> \/&gt;<\/span>\n                <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">button<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"close_btn\"<\/span> <span class=\"hljs-attr\">onClick<\/span>=<span class=\"hljs-string\">{deleteImage}<\/span>&gt;<\/span>\n                    Delete\n                <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">button<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span>\n        ) : <span class=\"hljs-literal\">null<\/span>;\n    }\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>This component accepts a URL and a <code>deleteImage<\/code> function. It renders an image and a button that triggers the <code>deleteImage<\/code> function when clicked.<\/p>\n<p>Let\u2019s now update our app component to include the <code>imagePreviewer<\/code> component and pass in our <code>id<\/code> and <code>previewURL<\/code> as props.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-wrap-lines\">    const App = () =&gt; {\n       \/\/ truncated for brevity\n      return (\n         <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">section<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"main\"<\/span>&gt;<\/span>\n                  \/\/ truncated for brevity\n                    {\/* this button will be used to capture the image*\/}\n                    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">button<\/span>\n                        <span class=\"hljs-attr\">disabled<\/span>=<span class=\"hljs-string\">{loading}<\/span>\n                        <span class=\"hljs-attr\">onClick<\/span>=<span class=\"hljs-string\">{captureAndUpload}<\/span>\n                        <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"capture_btn\"<\/span>\n                    &gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">button<\/span>&gt;<\/span>\n                     <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">ImagePreviewer<\/span> <span class=\"hljs-attr\">url<\/span>=<span class=\"hljs-string\">{prevURL}<\/span> <span class=\"hljs-attr\">deleteImage<\/span>=<span class=\"hljs-string\">{deleteImage}<\/span> \/&gt;<\/span>\n                <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">article<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">section<\/span>&gt;<\/span>\n        );\n    \n    }\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<h2>Fun with Filters<\/h2>\n<p>As mentioned in the introduction, Cloudinary\u2019s transformation features provide us with so many ways to manipulate media assets, including applying visual enhancements based on our application\u2019s needs. We will be using only a few filters but to see all available filters <a href=\"https:\/\/cloudinary.com\/documentation\/effects_and_artistic_enhancements\">check here<\/a>.<\/p>\n<p>Let\u2019s populate our array with different filter options. Add the following to your <code>filters<\/code> array in your <code>App.js<\/code> file.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">    <span class=\"hljs-keyword\">const<\/span> filters = &#91;\n        <span class=\"hljs-string\">\"none\"<\/span>,\n        <span class=\"hljs-string\">\"artistic\"<\/span>,\n        <span class=\"hljs-string\">\"sepia\"<\/span>,\n        <span class=\"hljs-string\">\"cartoonify\"<\/span>,\n        <span class=\"hljs-string\">\"vignette\"<\/span>,\n        <span class=\"hljs-string\">\"oilpaint\"<\/span>,\n        <span class=\"hljs-string\">\"grayscale\"<\/span>,\n        <span class=\"hljs-string\">\"vectorize\"<\/span>,\n        <span class=\"hljs-string\">\"pixelate\"<\/span>,\n    ];\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>Next, we update our <code>applyFilter<\/code> function to include the logic for applying different filters.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">    <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">applyFilter<\/span>(<span class=\"hljs-params\">filter, image<\/span>) <\/span>{\n        <span class=\"hljs-keyword\">switch<\/span> (filter) {\n            <span class=\"hljs-keyword\">case<\/span> <span class=\"hljs-string\">\"artistic\"<\/span>:\n                <span class=\"hljs-keyword\">return<\/span> image.effect(Effect.artisticFilter(<span class=\"hljs-string\">\"fes\"<\/span>));\n            <span class=\"hljs-keyword\">case<\/span> <span class=\"hljs-string\">\"sepia\"<\/span>:\n                <span class=\"hljs-keyword\">return<\/span> image.effect(Effect.sepia());\n            <span class=\"hljs-keyword\">case<\/span> <span class=\"hljs-string\">\"cartoonify\"<\/span>:\n                <span class=\"hljs-keyword\">return<\/span> image.effect(Effect.cartoonify());\n            <span class=\"hljs-keyword\">case<\/span> <span class=\"hljs-string\">\"vignette\"<\/span>:\n                <span class=\"hljs-keyword\">return<\/span> image.effect(Effect.vignette());\n            <span class=\"hljs-keyword\">case<\/span> <span class=\"hljs-string\">\"oilpaint\"<\/span>:\n                <span class=\"hljs-keyword\">return<\/span> image.effect(Effect.oilPaint());\n            <span class=\"hljs-keyword\">case<\/span> <span class=\"hljs-string\">\"grayscale\"<\/span>:\n                <span class=\"hljs-keyword\">return<\/span> image.effect(Effect.grayscale());\n            <span class=\"hljs-keyword\">case<\/span> <span class=\"hljs-string\">\"vectorize\"<\/span>:\n                <span class=\"hljs-keyword\">return<\/span> image.effect(Effect.vectorize());\n            <span class=\"hljs-keyword\">case<\/span> <span class=\"hljs-string\">\"pixelate\"<\/span>:\n                <span class=\"hljs-keyword\">return<\/span> image.effect(Effect.pixelate());\n            <span class=\"hljs-keyword\">default<\/span>:\n                <span class=\"hljs-keyword\">return<\/span> image;\n        }\n    }\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>The function <code>applyFilter<\/code> accepts a string and an image object. It uses a switch statement based on the filter object to modify and return the image object after applying the desired filter. We\u2019re using the <code>effect<\/code> action group and passing the appropriate action from the <code>Effect<\/code> factory method we imported.<\/p>\n<p>Now we have our <code>filters<\/code> array and <code>applyFilter<\/code> function, let\u2019s update our <code>FilterItem<\/code> component. Add the following to your <code>FilterItem<\/code> component in your <code>App.js<\/code> file.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">    <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">FilterItem<\/span>(<span class=\"hljs-params\">{ imgId, setPrevURL, filterName }<\/span>) <\/span>{\n        <span class=\"hljs-keyword\">let<\/span> image = cld.image(imgId);\n        image = applyFilter(filterName, image);\n        <span class=\"hljs-keyword\">const<\/span> imgURL = image.toURL();\n        <span class=\"hljs-keyword\">return<\/span> (\n            <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"filter_item\"<\/span> <span class=\"hljs-attr\">onClick<\/span>=<span class=\"hljs-string\">{()<\/span> =&gt;<\/span> setPrevURL(imgURL)}&gt;\n                <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">img<\/span> <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">{imgURL}<\/span> <span class=\"hljs-attr\">alt<\/span>=<span class=\"hljs-string\">\"\"<\/span> \/&gt;<\/span>\n                <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">span<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"filter_des\"<\/span>&gt;<\/span>{filterName}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">span<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span>\n        );\n    }\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>This function creates an image object using the <code>id<\/code> prop, and our Cloudinary instance then applies the desired filter. It also returns some JSX that includes a <code>div<\/code> that responds to click events and passes the URL representation of the transformed image object to modify the <code>prevURL<\/code> variable. It then displays the image and the filter name.<\/p>\n<p>We can now update the JSX returned from our App Component.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-wrap-lines\">    const App = () =&gt; {\n       \/\/ truncated for brevity\n        return (\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">section<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"main\"<\/span>&gt;<\/span>\n                <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">article<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"media_box\"<\/span>&gt;<\/span>\n                     \/\/ truncated for brevity\n                <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">article<\/span>&gt;<\/span>\n                <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">article<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"filter_container\"<\/span>&gt;<\/span>\n                    {id &amp;&amp; (\n                        <span class=\"hljs-tag\">&lt;&gt;<\/span>\n                            {filters.map((filter, index) =&gt; (\n                                <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">FilterItem<\/span>\n                                    <span class=\"hljs-attr\">imgId<\/span>=<span class=\"hljs-string\">{id}<\/span>\n                                    <span class=\"hljs-attr\">filterName<\/span>=<span class=\"hljs-string\">{filter}<\/span>\n                                    <span class=\"hljs-attr\">setPrevURL<\/span>=<span class=\"hljs-string\">{setPrevURL}<\/span>\n                                    <span class=\"hljs-attr\">key<\/span>=<span class=\"hljs-string\">{index}<\/span>\n                                \/&gt;<\/span>\n                            ))}\n                        <span class=\"hljs-tag\">&lt;\/&gt;<\/span>\n                    )}\n                <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">article<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">section<\/span>&gt;<\/span>\n        );\n    };\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>In the return statement of our <code>App<\/code> component, we first checked for the URL of our uploaded image. If it exists, we iterate over our filter strings and render our <code>FilterItem<\/code> component with the expected props. If we run our app now, we should be able to take pictures using our webcam and apply any filter of our choice.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/res.cloudinary.com\/jesse-thisdot\/image\/upload\/c_limit,w_2000\/f_auto\/q_auto\/v1633967311\/e-61325f69b4ddf000699b0fe3\/vphya3iii3ripd81me5h.png\" alt=\"\" loading=\"lazy\" class=\"c-transformed-asset\"  width=\"1600\" height=\"747\"\/><\/p>\n<p>Me, mySelfie and I btw your selfie is probably way better than mine. \ud83d\ude42<\/p>\n<h2>Conclusion<\/h2>\n<p>In this article, we were able to build an application that allows us to take pictures using a webcam component. We also used the image transformation features provided by Cloudinary to apply unique special effects to our captured images.<\/p>\n<p><strong>Some resources you may find helpful:<\/strong><\/p>\n<ul>\n<li>\n<a href=\"https:\/\/cloudinary.com\/documentation\/effects_and_artistic_enhancements#artistic_filter_effects\">Cloudinary\u2019s Visual Image Effects and Enhancements<\/a>\n<\/li>\n<li>\n<a href=\"https:\/\/www.npmjs.com\/package\/react-webcam\">React Webcam<\/a>\n<\/li>\n<li>\n<a href=\"https:\/\/reactjs.org\/\">React Documentation<\/a>\n<\/li>\n<\/ul>\n<\/div>","protected":false},"excerpt":{"rendered":"","protected":false},"author":41,"featured_media":28353,"comment_status":"","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_cloudinary_featured_overwrite":false,"footnotes":""},"categories":[1],"tags":[134,370,177,246,371],"class_list":["post-28352","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized","tag-guest-post","tag-image","tag-javascript","tag-react","tag-under-review"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.6 (Yoast SEO v26.9) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>React Selfie App with Cloudinary<\/title>\n<meta name=\"description\" content=\"In this article, we&#039;ll learn how to create an application that allows us to take pictures using a webcam and then use Cloudinary&#039;s image transformation features to add filters to our pictures.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/cloudinary.com\/blog\/guest_post\/react-selfie-app-with-cloudinary\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"React Selfie App with Cloudinary\" \/>\n<meta property=\"og:description\" content=\"In this article, we&#039;ll learn how to create an application that allows us to take pictures using a webcam and then use Cloudinary&#039;s image transformation features to add filters to our pictures.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/cloudinary.com\/blog\/guest_post\/react-selfie-app-with-cloudinary\/\" \/>\n<meta property=\"og:site_name\" content=\"Cloudinary Blog\" \/>\n<meta property=\"article:published_time\" content=\"2022-03-24T19:41:59+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924717\/Web_Assets\/blog\/6bc2df040241b170fad8f991746e11eb9f3a4302-1280x720-1_28353f7454\/6bc2df040241b170fad8f991746e11eb9f3a4302-1280x720-1_28353f7454.png?_i=AA\" \/>\n\t<meta property=\"og:image:width\" content=\"1280\" \/>\n\t<meta property=\"og:image:height\" content=\"720\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"NewsArticle\",\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/react-selfie-app-with-cloudinary\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/react-selfie-app-with-cloudinary\/\"},\"author\":{\"name\":\"\",\"@id\":\"\"},\"headline\":\"React Selfie App with Cloudinary\",\"datePublished\":\"2022-03-24T19:41:59+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/react-selfie-app-with-cloudinary\/\"},\"wordCount\":5,\"publisher\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/react-selfie-app-with-cloudinary\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924717\/Web_Assets\/blog\/6bc2df040241b170fad8f991746e11eb9f3a4302-1280x720-1_28353f7454\/6bc2df040241b170fad8f991746e11eb9f3a4302-1280x720-1_28353f7454.png?_i=AA\",\"keywords\":[\"Guest Post\",\"Image\",\"Javascript\",\"React\",\"Under Review\"],\"inLanguage\":\"en-US\",\"copyrightYear\":\"2022\",\"copyrightHolder\":{\"@id\":\"https:\/\/cloudinary.com\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/react-selfie-app-with-cloudinary\/\",\"url\":\"https:\/\/cloudinary.com\/blog\/guest_post\/react-selfie-app-with-cloudinary\/\",\"name\":\"React Selfie App with Cloudinary\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/react-selfie-app-with-cloudinary\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/react-selfie-app-with-cloudinary\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924717\/Web_Assets\/blog\/6bc2df040241b170fad8f991746e11eb9f3a4302-1280x720-1_28353f7454\/6bc2df040241b170fad8f991746e11eb9f3a4302-1280x720-1_28353f7454.png?_i=AA\",\"datePublished\":\"2022-03-24T19:41:59+00:00\",\"description\":\"In this article, we'll learn how to create an application that allows us to take pictures using a webcam and then use Cloudinary's image transformation features to add filters to our pictures.\",\"breadcrumb\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/react-selfie-app-with-cloudinary\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/cloudinary.com\/blog\/guest_post\/react-selfie-app-with-cloudinary\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/react-selfie-app-with-cloudinary\/#primaryimage\",\"url\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924717\/Web_Assets\/blog\/6bc2df040241b170fad8f991746e11eb9f3a4302-1280x720-1_28353f7454\/6bc2df040241b170fad8f991746e11eb9f3a4302-1280x720-1_28353f7454.png?_i=AA\",\"contentUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924717\/Web_Assets\/blog\/6bc2df040241b170fad8f991746e11eb9f3a4302-1280x720-1_28353f7454\/6bc2df040241b170fad8f991746e11eb9f3a4302-1280x720-1_28353f7454.png?_i=AA\",\"width\":1280,\"height\":720},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/react-selfie-app-with-cloudinary\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/cloudinary.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"React Selfie App with Cloudinary\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#website\",\"url\":\"https:\/\/cloudinary.com\/blog\/\",\"name\":\"Cloudinary Blog\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/cloudinary.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\",\"name\":\"Cloudinary Blog\",\"url\":\"https:\/\/cloudinary.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA\",\"contentUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA\",\"width\":312,\"height\":60,\"caption\":\"Cloudinary Blog\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"React Selfie App with Cloudinary","description":"In this article, we'll learn how to create an application that allows us to take pictures using a webcam and then use Cloudinary's image transformation features to add filters to our pictures.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/cloudinary.com\/blog\/guest_post\/react-selfie-app-with-cloudinary\/","og_locale":"en_US","og_type":"article","og_title":"React Selfie App with Cloudinary","og_description":"In this article, we'll learn how to create an application that allows us to take pictures using a webcam and then use Cloudinary's image transformation features to add filters to our pictures.","og_url":"https:\/\/cloudinary.com\/blog\/guest_post\/react-selfie-app-with-cloudinary\/","og_site_name":"Cloudinary Blog","article_published_time":"2022-03-24T19:41:59+00:00","og_image":[{"width":1280,"height":720,"url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924717\/Web_Assets\/blog\/6bc2df040241b170fad8f991746e11eb9f3a4302-1280x720-1_28353f7454\/6bc2df040241b170fad8f991746e11eb9f3a4302-1280x720-1_28353f7454.png?_i=AA","type":"image\/png"}],"twitter_card":"summary_large_image","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"NewsArticle","@id":"https:\/\/cloudinary.com\/blog\/guest_post\/react-selfie-app-with-cloudinary\/#article","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/react-selfie-app-with-cloudinary\/"},"author":{"name":"","@id":""},"headline":"React Selfie App with Cloudinary","datePublished":"2022-03-24T19:41:59+00:00","mainEntityOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/react-selfie-app-with-cloudinary\/"},"wordCount":5,"publisher":{"@id":"https:\/\/cloudinary.com\/blog\/#organization"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/react-selfie-app-with-cloudinary\/#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924717\/Web_Assets\/blog\/6bc2df040241b170fad8f991746e11eb9f3a4302-1280x720-1_28353f7454\/6bc2df040241b170fad8f991746e11eb9f3a4302-1280x720-1_28353f7454.png?_i=AA","keywords":["Guest Post","Image","Javascript","React","Under Review"],"inLanguage":"en-US","copyrightYear":"2022","copyrightHolder":{"@id":"https:\/\/cloudinary.com\/#organization"}},{"@type":"WebPage","@id":"https:\/\/cloudinary.com\/blog\/guest_post\/react-selfie-app-with-cloudinary\/","url":"https:\/\/cloudinary.com\/blog\/guest_post\/react-selfie-app-with-cloudinary\/","name":"React Selfie App with Cloudinary","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/react-selfie-app-with-cloudinary\/#primaryimage"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/react-selfie-app-with-cloudinary\/#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924717\/Web_Assets\/blog\/6bc2df040241b170fad8f991746e11eb9f3a4302-1280x720-1_28353f7454\/6bc2df040241b170fad8f991746e11eb9f3a4302-1280x720-1_28353f7454.png?_i=AA","datePublished":"2022-03-24T19:41:59+00:00","description":"In this article, we'll learn how to create an application that allows us to take pictures using a webcam and then use Cloudinary's image transformation features to add filters to our pictures.","breadcrumb":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/react-selfie-app-with-cloudinary\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/cloudinary.com\/blog\/guest_post\/react-selfie-app-with-cloudinary\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/guest_post\/react-selfie-app-with-cloudinary\/#primaryimage","url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924717\/Web_Assets\/blog\/6bc2df040241b170fad8f991746e11eb9f3a4302-1280x720-1_28353f7454\/6bc2df040241b170fad8f991746e11eb9f3a4302-1280x720-1_28353f7454.png?_i=AA","contentUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924717\/Web_Assets\/blog\/6bc2df040241b170fad8f991746e11eb9f3a4302-1280x720-1_28353f7454\/6bc2df040241b170fad8f991746e11eb9f3a4302-1280x720-1_28353f7454.png?_i=AA","width":1280,"height":720},{"@type":"BreadcrumbList","@id":"https:\/\/cloudinary.com\/blog\/guest_post\/react-selfie-app-with-cloudinary\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/cloudinary.com\/blog\/"},{"@type":"ListItem","position":2,"name":"React Selfie App with Cloudinary"}]},{"@type":"WebSite","@id":"https:\/\/cloudinary.com\/blog\/#website","url":"https:\/\/cloudinary.com\/blog\/","name":"Cloudinary Blog","description":"","publisher":{"@id":"https:\/\/cloudinary.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/cloudinary.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/cloudinary.com\/blog\/#organization","name":"Cloudinary Blog","url":"https:\/\/cloudinary.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA","contentUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA","width":312,"height":60,"caption":"Cloudinary Blog"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":""}]}},"jetpack_featured_media_url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924717\/Web_Assets\/blog\/6bc2df040241b170fad8f991746e11eb9f3a4302-1280x720-1_28353f7454\/6bc2df040241b170fad8f991746e11eb9f3a4302-1280x720-1_28353f7454.png?_i=AA","_links":{"self":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/28352","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/users\/41"}],"replies":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/comments?post=28352"}],"version-history":[{"count":0,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/28352\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media\/28353"}],"wp:attachment":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media?parent=28352"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/categories?post=28352"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/tags?post=28352"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}