cloudinary / frontend-frameworks

Cloudinary javascript frontend frameworks SDKs, including Shared HTML layer, Angular, React and Vue SDKs
https://www.cloudinary.com
MIT License
43 stars 16 forks source link

Quality transformation gets added twice (React SDK) #169

Open leahwchang opened 2 years ago

leahwchang commented 2 years ago

For which package is this issue?

React

Describe the issue in a sentence or two.

Hi, I have a custom reusable react "image" component that utilizes AdvancedImage. The component takes in a prop 'imageQuality' and it's a string, I have a function that simply chains .quality(imageQuality) to the cloudinary instance, which is then passed to AdvancedImage.

When I console log the tranformed url, I noticed that quality shows up twice... for example: https://res.cloudinary.com/myCloudName/image/upload/q_80/q_80/v1/xxxx.png

Any help is appreciated... thank you.

Issue Type (Can be multiple)

[ ] Build - Can’t install or import the SDK [ ] Performance - Performance issues [ x] Behaviour - Functions aren’t working as expected [ ] Documentation - Inconsistency between the docs and behaviour [ ] Incorrect Types [ ] Other (Specify)

related Cloudinary imports:

import { AdvancedImage, responsive, placeholder } from '@cloudinary/react'
import { Cloudinary } from '@cloudinary/url-gen';
import {scale, fill, limitFill, crop} from "@cloudinary/url-gen/actions/resize";
import {dpr} from "@cloudinary/url-gen/actions/delivery";

function that chains .quality to image instance:

// get image quality
    function getQuality(imageQuality) {
    if (imageQuality === 'auto') {
      return 'q_auto:best'
    } else if (typeof +imageQuality && !Number.isNaN(+imageQuality)) {
      return Number(imageQuality);
    }
  }

 // chain quality
  function chainQuality(baseImage, imageQuality) {
    let transformedImage = baseImage.quality(getQuality(imageQuality));
    return transformedImage;
  }

using reducer and useEffect to conditionally chain 'quality' function:

  function reducer(state, action) {
    switch (action.type) {
      case 'quality':
        return {...state, image: chainQuality(state.image, state.imageQuality)};
      // ... with other action types 
    }
  }

  const initialState = {
    image: img,
    imageQuality: imageQuality,
    // ... with other props
  };

  const [state, dispatch] = useReducer(reducer, initialState);

  useEffect(() => {
    if (imageQuality) {
      dispatch({ type: 'quality' });
    }
    // ... with other dispatches
  }, []);

result/problem - quality shows up twice in url:

 console.log('state', state.image.toURL());
 // returns something like https://res.cloudinary.com/myCloudName/image/upload/q_80/q_80/v1/xxxx.png

Versions and Libraries (fill in the version numbers) Node - v16.16.0 NPM - 8.11.0

Package.json includes: "@cloudinary/react": "^1.4.1", "@cloudinary/url-gen": "^1.8.0",

ghost commented 2 years ago

Hi @leahwchang I was not able to reproduce this using the following code. Maybe your chainQuality() function runs twice ? could be react related, see here for example: https://stackoverflow.com/questions/60618844/react-hooks-useeffect-is-called-twice-even-if-an-empty-array-is-used-as-an-ar

import React from 'react'
import {Cloudinary} from "@cloudinary/url-gen";
import {AdvancedImage} from '@cloudinary/react';

const myCld = new Cloudinary({cloud: {cloudName: 'demo'}});

export const App = () => {
  const myCld = new Cloudinary({cloud: {cloudName: 'yourCloudName'}});
  const img = myCld.image('publicId');
  img.quality(80);

  // Render your component.
  return (
    <div>
      <AdvancedImage cldImg={img}/>
    </div>
  )
};