I have a react color picker that I am using to create a custom 16 color gradient. I use a dropdown to select the color I want to edit and then use the color picker to pick the color. This edits an array that is called to style each box of the dropdown. My end goal is to change the background of each entry in the dropdown to the corresponding color in the gradient.
var gradientColors = ['#000000', '#000000', '#000000', '#000000', '#000000', '#000000', '#000000', '#000000', '#000000', '#000000', '#000000', '#000000', '#000000', '#000000', '#000000', '#000000']; function ChangeCustomGradientColor(eventKey, color) { gradientColors[eventKey] = color; } function App() { const [color, setColor] = useState('#fff') const [showColorPicker, setShowColorPicker] = useState(false) const [eKey, setEventKey] = useState(''); const eventKeySelect=(e)=>{ setEventKey(e) setShowColorPicker(showColorPicker => !showColorPicker) } return ( <div className="App" id="top"> <header className="App-header" id="mid"> <Dropdown onSelect={eventKeySelect}> <Dropdown.Toggle variant="success" id="custom-color-change"> Change Custom Gradient Color </Dropdown.Toggle> <Dropdown.Menu > <Dropdown.Item id="cust0" eventKey="0" style={{backgroundColor:gradientColors[0]}}>1</Dropdown.Item> <Dropdown.Item id="cust1" eventKey="1" style={{backgroundColor:gradientColors[1]}}>2</Dropdown.Item> <Dropdown.Item id="cust2" eventKey="2" style={{backgroundColor:gradientColors[2]}}>3</Dropdown.Item> <Dropdown.Item id="cust3" eventKey="3" style={{backgroundColor:gradientColors[3]}}>4</Dropdown.Item> <Dropdown.Item id="cust4" eventKey="4" style={{backgroundColor:gradientColors[4]}}>5</Dropdown.Item> <Dropdown.Item id="cust5" eventKey="5" style={{backgroundColor:gradientColors[5]}}>6</Dropdown.Item> <Dropdown.Item id="cust6" eventKey="6" style={{backgroundColor:gradientColors[6]}}>7</Dropdown.Item> <Dropdown.Item id="cust7" eventKey="7" style={{backgroundColor:gradientColors[7]}}>8</Dropdown.Item> <Dropdown.Item id="cust8" eventKey="8" style={{backgroundColor:gradientColors[8]}}>9</Dropdown.Item> <Dropdown.Item id="cust9" eventKey="9" style={{backgroundColor:gradientColors[9]}}>10</Dropdown.Item> <Dropdown.Item id="cust10" eventKey="10" style={{backgroundColor:gradientColors[10]}}>11</Dropdown.Item> <Dropdown.Item id="cust11" eventKey="11" style={{backgroundColor:gradientColors[11]}}>12</Dropdown.Item> <Dropdown.Item id="cust12" eventKey="12" style={{backgroundColor:gradientColors[12]}}>13</Dropdown.Item> <Dropdown.Item id="cust13" eventKey="13" style={{backgroundColor:gradientColors[13]}}>14</Dropdown.Item> <Dropdown.Item id="cust14" eventKey="14" style={{backgroundColor:gradientColors[14]}}>15</Dropdown.Item> <Dropdown.Item id="cust15" eventKey="15" style={{backgroundColor:gradientColors[15]}}>16</Dropdown.Item> </Dropdown.Menu> </Dropdown> { showColorPicker && ( <ChromePicker disableAlpha={true} color={color} onChangeComplete={updatedColor => ChangeCustomGradientColor(eKey, updatedColor)} /> )} </header> </div> ) }
I’ve also tried getElementByID
in my ChangeCustomGradientColor
function like so
function ChangeCustomGradientColor(eventKey, color) { let elementID = "cust" + eventKey; document.getElementByID(elementID).style.backgroundColor = color; }
I’ve been copying/pasting and learning but now am at the point where I just need to sit down and take a full JS class before I move on. Any help or advice is appreciated.
Advertisement
Answer
The gradientColors
are being mutated by reference instead of state, so your Dropdown.Item components go stale, they never know when to re-render. To fix that you just bring gradientColors
into state with a useState
. Here’s a codesandebox example.
instead of mutating
initialGradientColors[eventKey] = color.hex;
you need to mutate via state so that it triggers the appropriate re-renders.
const [gradientColors, setGradientColors] = useState(initialGradientColors); // in some callback setGradientColors(prevGradientColors => { const updated = prevGradientColors.map((color, index) => { if(index === eventKey){ return newColor; } return color; }) return updated; }))