javascriptreactjsreduxreact-reduxreact-color

Color picker from react-color doesn't work properly


I'm using react-color and this tutorial to implemented a ChromePicker.

How I'm expecting it ti work:

So far it works like this:

Here is a screenshot of it:

enter image description here

Why is the ChromePicker so badly? Is there a way to solve it? And also, I would like to save the new color on Company only after the ChromePicker is closed (it seems that onChangeComplete is not triggered by that)

This is the code:

 import React from 'react';
    import { Button, Icon } from 'semantic-ui-react';
    import { ChromePicker } from 'react-color';
    import { connect } from 'react-redux';
    import { Creators } from '../../actions';
    
    
    class Banner extends React.PureComponent {
      constructor(props) {
        super(props);
        this.state = {
          displayColorPicker: false,
        };
      }
    
      handleClick = () => {
        this.setState({ displayColorPicker: true });
      };
    
      handleClose = () => {
        this.setState({ displayColorPicker: false });
      };
    
      handleChangeComplete = colors => {
        const {
          name,
          color,
        } = this.state;
        this.setState({ color: colors.hex });
        const { updateCompany } = this.props; // company is the entity from props that is updated
                                              // it contains 2 values, its name and its color
        updateCompany(this.props.company._id, {
          name,
          color,
        });
      };
    
    
    
      render() {
        this.props.color.color.color = this.state.color;
        const popover = { // this is not essential, it's some styling for the picker
          position: 'absolute',
          zIndex: '2',
        };
        const cover = { // same as for popover
          position: 'fixed',
          top: '0px',
          right: '0px',
          bottom: '0px',
          left: '0px',
        };
        const {company } = this.props; // gets the company from props
        return (
          <div className="banner-container settings-banner">   
     
      //the below div with its style is updating in real time when the color is changed 
                  <div style={{ backgroundColor: this.state.color }}>              
                    <div>
                      <Button
                        className="select-color-btn"
                        onClick={this.handleClick}>
                        Select a color
                      </Button>
                      {this.state.displayColorPicker ? (
                        <div style={popover}>
                          <div
                            style={cover}
                            onClick={this.handleClose}
                            onKeyDown={this.handleClick}
                            role="button"
                            tabIndex="0"
                            aria-label="Save"
                          />
                          <ChromePicker
                            color={this.props.company.color}
                            onChangeComplete={this.handleChangeComplete}
                          />
                        </div>
                      ) : null}
                    </div>
                  </div>
            
          </div>
        );
      }
    }
    
    const mapStateToProps = state => ({
      company: state.companies.selectedCompany,
    });
    
    const mapDispatchToProps = {
      updateCompany: Creators.updateCompanyRequest,
    };
    
    export default connect(mapStateToProps, mapDispatchToProps)(Banner);

Solution

  • In order to make the ChromePicker work (moving the hue bar and the circle inside the "big square" it must be added onChange function and glue it to onHandleChange.

    Also, inside onHandleChangeComplete, the color must not be taken from the state but from function's parameter, colors:

    import React from 'react'; import { Button, Icon } from 'semantic-ui-react'; import { ChromePicker } from 'react-color'; import { connect } from 'react-redux'; import { Creators } from '../../actions';

    class Banner extends React.PureComponent {
      constructor(props) {
        super(props);
        this.state = {
          displayColorPicker: false,
        };
      }
    
      handleClick = () => {
        this.setState({ displayColorPicker: true });
      };
    
      handleClose = () => {
        this.setState({ displayColorPicker: false });
      };
    
      handleChange2 = colors => {
        this.setState({ background: colors.hex });
     };
    
      handleChangeComplete = colors => {
        this.setState({ background: colors.hex });
        const {
          name,
        } = this.state;
        const color = colors.hex;
        this.setState({ color: colors.hex });
        const { updateCompany } = this.props;                                           
        updateCompany(this.props.company._id, {
          name,
          color,
        });
      };
    
    
    
      render() {
        this.props.color.color.color = this.state.color;
        const popover = { // this is not essential, it's some styling for the picker
          position: 'absolute',
          zIndex: '2',
        };
        const cover = { // same as for popover
          position: 'fixed',
          top: '0px',
          right: '0px',
          bottom: '0px',
          left: '0px',
        };
        const {company } = this.props; // gets the company from props
        return (
          <div className="banner-container settings-banner">   
                  <div style={{ backgroundColor: this.state.color }}>              
                    <div>
                      <Button
                        className="select-color-btn"
                        onClick={this.handleClick}>
                        Select a color
                      </Button>
                      {this.state.displayColorPicker ? (
                        <div style={popover}>
                          <div
                            style={cover}
                            onClick={this.handleClose}
                            onKeyDown={this.handleClick}
                            role="button"
                            tabIndex="0"
                            aria-label="Save"
                          />
                          <ChromePicker
                            color={this.state.background}
                            onChange={this.handleChange2} 
                            onChangeComplete={this.handleChangeComplete}
                          />
                        </div>
                      ) : null}
                    </div>
                  </div>
            
          </div>
        );
      }
    }
    
    const mapStateToProps = state => ({
      company: state.companies.selectedCompany,
    });
    
    const mapDispatchToProps = {
      updateCompany: Creators.updateCompanyRequest,
    };
    
    export default connect(mapStateToProps, mapDispatchToProps)(Banner);