The Dead Man
The Dead Man

Reputation: 5566

change background color using react color picker

I have a section in which I want users to be able to change the background color using react color picker and react-redux, unfortunately, the background color is not changing / not updating to a new color.

Live code in codesandbox: change background color

Source code:

  import React, { useState, useEffect } from "react";
import { useSelector, useDispatch } from "react-redux";
import { ChromePicker } from "react-color";
import Details from "./Details";

const Settings = () => {
  const fields = useSelector((state) => state);
  const dispatch = useDispatch();
  const [colorRgb, setColorRgb] = useState("#000");

  useEffect(() => {
    updateColor();
  }, []);

  const updateColor = () => {
    dispatch({
      type: "change",
      name: "socialColor",
      value: colorRgb
    });
  };
  console.log("current color", colorRgb);
  console.log("current color", fields.color);
  return (
    <div>
      <div>
        <Details />
        <h1>Edit </h1>
        <div className="container">
          <ChromePicker
            renderers={false}
            color={colorRgb}
            onChange={(e) => setColorRgb(e.hex)}
          />
          <span
            className="testa"
            style={{
              background: fields.color,
              color: "#fff"
            }}
          >
            Change my background color
          </span>
        </div>
      </div>
    </div>
  );
};

export default Settings;

What is wrong with my code.?

Upvotes: 0

Views: 3058

Answers (3)

Linda Paiste
Linda Paiste

Reputation: 42198

You are only calling the updateColor function which calls dispatch one time when the component mounts. This doesn't make any sense because your redux value will always be black.

If you want to store "pending" changes in the component then you would use a local component state and call dispatch when clicking a "Submit" button.

Probably you want to call dispatch on every change and get rid of the local useState.

@ibra is correct about needing to format the color object into a string but you can write it more concisely.

It's up to you whether you want to convert from an object to a string before you store it in redux or after you retrieve it.

import React from "react";
import { useSelector, useDispatch } from "react-redux";
import { ChromePicker } from "react-color";
import Details from "./Details";

export const rgbaString = ({r, g, b, a = 1}) => `rgba(${r},${g},${b},${a})`

const Settings = () => {
  const colorRgb = useSelector((state) => state.color);
  const dispatch = useDispatch();

  const onChangeColor = (e) => {
    dispatch({
      type: "change",
      name: "color",
      value: e.rgb
    });
  };
  
  return (
    <div>
      <div>
        <Details />
        <h1>Edit </h1>
        <div className="container">
          <ChromePicker
            renderers={false}
            color={colorRgb}
            onChange={onChangeColor}
          />
          <span
            className="testa"
            style={{
              background: rgbaString(colorRgb),
              color: "#fff"
            }}
          >
            Change my background color
          </span>
        </div>
      </div>
    </div>
  );
};

export default Settings;

Upvotes: 2

ibra
ibra

Reputation: 433

You just need to set background in syntax of rgba(r, g, b, a) instead of {r, g, b, a} which is invalid css

import React, { useState, useEffect } from "react";
import { useSelector, useDispatch } from "react-redux";
import { ChromePicker } from "react-color";

const Settings = () => {
  const fields = useSelector((state) => state);
  const dispatch = useDispatch();
  const [colorRgb, setColorRgb] = useState(fields.color);

  useEffect(() => {
    updateColor();
  }, []);

  const updateColor = () => {
    dispatch({
      type: "change",
      name: "socialColor",
      value: colorRgb
    });
  };
  console.log("current color", colorRgb);
  return (
    <div>
      <div>
        <h1>Edit </h1>
        <div className="container">
          <ChromePicker
            renderers={false}
            color={colorRgb}
            onChange={(e) => setColorRgb(e.rgb)}
          />
          <span
            className="testa"
            style={{
              background:
                "rgba(" +
                colorRgb.r +
                "," +
                colorRgb.g +
                "," +
                colorRgb.b +
                "," +
                colorRgb.a +
                ")",
              color: "#fff"
            }}
          >
            Change my background color
          </span>
        </div>
      </div>
    </div>
  );
};

export default Settings;

Upvotes: 2

oguzduran
oguzduran

Reputation: 24

The problem will be fixed if you get the hex code instead of rgb

your code

   <ChromePicker
     renderers={false}
     color={colorRgb}
     onChange={(e) => colorChange(e.rgb)}
   />

must be

   <ChromePicker
     renderers={false}
     color={colorRgb}
     onChange={(e) => colorChange(e.hex)}
   />

Upvotes: 1

Related Questions