Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

iro.js with React #54

Closed
Ermilin opened this issue Feb 26, 2019 · 9 comments
Closed

iro.js with React #54

Ermilin opened this issue Feb 26, 2019 · 9 comments

Comments

@Ermilin
Copy link

Ermilin commented Feb 26, 2019

Hi, this project looks very promising.

How do I use this with react? I am trying to create a new picker with a unique id in every loop of my map function.

screenshot 2019-02-26 at 19 36 16

As seen in this picture I want to control the color of each controller with a picker for every card.

@jaames
Copy link
Owner

jaames commented Feb 26, 2019

Hey @Ermilin, thank you for the kind words!

At the moment I would recommend wrapping the color picker with a react component, something like this:

class IroColorPicker extends React.Component {
  componentDidMount() {
    const { props } = this;
    // create a new iro color picker and pass component props to it
    this.colorPicker = new iro.ColorPicker(this.el, props);
    // call onColorChange prop whenever the color changes
    this.colorPicker.on('color:change', (color) => {
      if (props.onColorChange) props.onColorChange(color);
    });
  }

  componentDidUpdate() {
    // isolate color from the rest of the props
    const {color, ...colorPickerState} = this.props;
    // update color
    if (color) this.colorPicker.color.set(color);
    // push rest of the component props to the colorPicker's state
    this.colorPicker.setState(colorPickerState);
  }

  render() {
    return (
      <div ref={el => this.el = el} />
    );
  }
}

This component will take all the iro.ColorPicker options via props, and it will update the color picker whenever any of these prop values change. The onColorChange prop that accepts a callback function which will be called whenever the selected color changes.

Example usage:

<IroColorPicker
  color={ '#fff' }
  onColorChange={ (color) => { console.log(color.hexString) } }
/>

I understand this isn't ideal. I fully intend to give the library a "true" React port when I have the time, but until then I hope that this suffices.

@Ermilin
Copy link
Author

Ermilin commented Feb 26, 2019

Thank you for the quick reply, I'll look into it tomorrow. Good night!

@Ermilin
Copy link
Author

Ermilin commented Feb 28, 2019

I can't get it working, could you provide a working example with several colorpicker componenets?

Error: Uncaught TypeError: Cannot read property 'appendChild' of null

@Ermilin
Copy link
Author

Ermilin commented Feb 28, 2019

Your edited post works like a charm! Thank you so much for this project! Love ya.

@Ermilin Ermilin closed this as completed Feb 28, 2019
@jaames
Copy link
Owner

jaames commented Feb 28, 2019

Ahah, no worries! Sorry for not making the edit clearer -- my initial example wasn't tested ":)

Best of luck with your project!

@zenzoa
Copy link

zenzoa commented Apr 7, 2019

When I try using iro.js (4.2.2) with Preact (8.4.2), I find that once the parent component gets updated, iro disappears. Any ideas on how to prevent that from happening without creating a new color picker every update? EDIT: Found a workaround. If I use shouldComponentUpdate instead of componentDidUpdate, I can use nextProps to update iro and then return false so the component doesn't actually redraw.

@jaames
Copy link
Owner

jaames commented Apr 7, 2019

Nice catch @sarahgould ! If that doesn't work out I'm wondering if it might be better to replace React.Component with React.PureComponent (which is also in preact-compat iirc), as recommended by the React docs?

@bertyhell
Copy link

bertyhell commented Dec 22, 2019

With hooks it looks something like this:

import React, { createRef, FunctionComponent, MutableRefObject, RefObject, useEffect, useRef } from 'react';
import iro from '@jaames/iro';

interface IroColorPicker {
  on: (action: string, callback: Function) => void;
  color: {
    hexString: string;
    set: (value: any) => void;
    setState: (state: any) => void;
  }
}

export interface ColorInputProps {
  className?: string;
  value?: string;
  onChange?: (color: string) => void;
}

const ColorInput: FunctionComponent<ColorInputProps> = ({
                                                          className,
                                                          value = '#850000',
                                                          onChange = () => {
                                                          }
                                                        }) => {
  let colorPicker: MutableRefObject<IroColorPicker | null> = useRef<IroColorPicker | null>(null);
  let el: RefObject<HTMLDivElement> = createRef<HTMLDivElement>();

  useEffect(() => {
    if (!el.current) {
      return;
    }
    if (!colorPicker.current) {
      // create a new iro color picker and pass component props to it
      colorPicker.current = new iro.ColorPicker(el.current, { color: value });
      // call onColorChange prop whenever the color changes
      if (!colorPicker.current) {
        return;
      }
      colorPicker.current.on('color:change', (color: { hexString: string }) => {
        onChange(color.hexString);
      });
    } else if(value !== colorPicker.current.color.hexString) {
      colorPicker.current.color.set(value);
    }
  });

  return  <div ref={el} />;
};

export default ColorInput;

@mydudechris
Copy link

mydudechris commented Nov 1, 2021

@jaames your solution works well for setting up a single picker & slider, but how would you address a layout with multiple components? For example, a wheel + ui.Slider (value) + ui.Slider (alpha). See attached, in this instance I'm adding a box and hue slider. The IroColorPicker props show the items and on inspecting the page, I can see that the items are rendered to the DOM but they appear with a 0 width/height and are not visible. If I pull the layout prop, it presents the default value. What am I missing?

image

Thanks! 👍

Update figured it out, needed to import iro in the file for the IroColorPicker to recognize the component option iro.ui.Wheel/Slider...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants