Reputation: 5566
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
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
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
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