-1

In ReactJS I would like to use a functional component to change the background color of a button when it is pressed. The color's should be stored in an array and when button is pressed should cycle through changing the background colors.

Here's what I have tried:

import React, { useState } from "react";

export default function Button(props) {
    const [colors, setColour] = useState(['red', 'green', 'blue', 'orange', 'yellow']);

    const changeBtncolor = () => {
        setColour();
    }

    return (
        colors.map((color, id) => {
            return
            <Button key={id} type="button"
            style={{backgroundColor: color}}
            onclick={changeBtncolor(props)}>Change color
            </Button>
        })
    )
}
Alex
  • 206
  • 2
  • 10
kb kb
  • 19
  • 1
  • 3
  • Your question is unclear (you say "the" button, but you create one for every colour in the array, you say "change the background colour" but you don't say to what) and your code doesn't make sense (`colours` starts out an an array, but when you click the button you set it to a single value in that array, at least you would if you weren't making [this error](https://stackoverflow.com/questions/7137401/why-is-the-method-executed-immediately-when-i-use-settimeout). – Quentin Nov 11 '20 at 21:27
  • 1
    It looks like @kbkb needs to clarify the question. Would you at least like to tell us what is expected out of the code, so that we can at least try to solve it in a different way possible? – Praveen Kumar Purushothaman Nov 11 '20 at 21:34
  • Apologies, I meant "React functional button component, which will cycle through an array of colours passed to the component by a prop (`colors: string[]`) when the button is clicked, such that each time the button is clicked, it changes the button’s colour to the next in the array" – kb kb Nov 11 '20 at 21:39
  • @kbkb In simple way we can do it. I'll write a very simple code for that and update my answer, give me few mins. – Praveen Kumar Purushothaman Nov 11 '20 at 21:42
  • @kbkb I have answered plus I have got a preview too. Check it out. Also see, [What should I do when someone answers my question?](https://stackoverflow.com/help/someone-answers). – Praveen Kumar Purushothaman Nov 11 '20 at 21:52

2 Answers2

0

First. The state is used to store things which change.

The array of colours isn't going to change, so don't store it in the state.

The selected colour is going to change, so do store that in the state. In this case, you can do that by using the index of the colour in the array.

Next, when the colour changes, you want to pick the next one. That's just a matter of incrementing the index. However, when you get to the end you'll probably want to loop back. So check for that.

Third, since you only want one button, create only one button. Don't loop over the array of colours there.

Use the value from the state to assign the background colour.

onclick is onClick in React.

Just pass the function for setting the nextColour. It doesn't need any arguments.

Finally, if you want an HTML button element then it is <button>. Starting a JSX name with a capital letter means you are using a component. There are plenty of third-party Button components, but you aren't importing any. Trying to use <Button> here would be recursively using the component you just created.


Live demo is third-party hosted due to the dependancies.

import React, { useState } from "react";

const colours = ['red', 'green', 'blue', 'orange', 'yellow'];

export function Button(props) {
    const [selectedColourIndex, setColourIndex] = useState(0);

    const nextColour = () => {
        const newColourIndex = selectedColourIndex + 1;
        if (colours[newColourIndex]) 
            setColourIndex(newColourIndex);
        else
            setColourIndex(0);
    }

    return (<button type="button" style={{backgroundColor: colours[selectedColourIndex]}}
            onClick={nextColour}>Change color</button>);
}
Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
-1

A working example for you is:

import React, { useState } from "react";

export default function App() {
  const Colors = ["red", "green", "blue", "orange", "yellow"];
  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
      {Colors.map((color, key) => (
        <Button Color={color} Colors={Colors} key={key} />
      ))}
    </div>
  );
}

function Button({ Color, Colors }) {
  const [color, setColor] = useState(Color);
  const handleChange = (e) => {
    e.preventDefault();
    setColor(Colors[Math.floor(Math.random() * Colors.length)]);
  };
  const style = {
    backgroundColor: color
  };
  return (
    <button onClick={handleChange} style={style}>
      Click Me!
    </button>
  );
}

Demo: https://00qh5.csb.app/

Preview

preview


Previous Answer:

You have an error, if you're not using () after return statement. It becomes Automatic Semicolon Insertion in JavaScript in JavaScript and it will not work. So don't leave the return statement hanging.

You're supposed to use state only for those things that'll change. Not for storing variables.

Also, I would avoid using fragments <></> here as it doesn't make any sense. So I removed that as well.

The onClick={changeBtncolor(props)} will execute the changeBtncolor(props) immediately, so you need to wrap it inside a handler function.

You're not passing any value to the setColour function inside the changeBtncolor function, but you're passing props, which there's no clarity, so I have changed the way the function now works, by using a colour name instead from the props.

Notice the difference between color and the prop colour. Here's an updated React code that will work as per your expectations.

import React, { useState } from "react";

export default function Button({ colour }) {
  const [colors, setColour] = useState([
    "red",
    "green",
    "blue",
    "orange",
    "yellow"
  ]);

  const changeBtncolor = color => {
    setColour(color);
  };

  return colors.map((color, id) => (
    <Button
      key={id}
      type="button"
      style={{ backgroundColor: color }}
      onclick={() => changeBtncolor(colour)}
    >
      Change color
    </Button>
  ));
}
Praveen Kumar Purushothaman
  • 164,888
  • 24
  • 203
  • 252
  • Clicking the button there won't change the colour of anything, it will just throw an exception as `colors` is replaced by a string which doesn't have a `map` property. – Quentin Nov 11 '20 at 21:28
  • @Quentin You're right! This is the worst answer I have written then. Should I fix the code or should I remove my answer altogether? – Praveen Kumar Purushothaman Nov 11 '20 at 21:29
  • 1
    I think the question is unanswerable in its current state (just from the lack of clarity over what they are asking, not even counting all the different problems with the attempt). YMMV. – Quentin Nov 11 '20 at 21:32
  • Once this question gets closed and if the OP doesn't return, I am planning to delete this answer. I just worked really hard for this answer just to find that the question is unanswerable! @Quentin – Praveen Kumar Purushothaman Nov 11 '20 at 21:38
  • @Quentin Updated my answer. – Praveen Kumar Purushothaman Nov 11 '20 at 21:54
  • Thanks to you too @PraveenKumarPurushothaman great feedback! – kb kb Nov 11 '20 at 22:13
  • The OP asked for it to cycle through the colors not choose one at random that would mean to cycle through them in the order they are defined and once reaching last index in array restart at 0 index. I would say Quentin has the most understandable solution. @PraveenKumarPurushothaman – Alex Nov 11 '20 at 23:30
  • @Alex I agree. I'll remove my answer. Thanks. – Praveen Kumar Purushothaman Nov 11 '20 at 23:37