1

I'm 100% sure this has been answered (here and here and here?), but I just can't figure out how to apply the answers that have already been given. If you're going to mark this as a duplicate, please include a note about how to apply the existing answers to my specific issue. Thanks!

Working on this tutorial and having a great time. I get the initial code up and running, I can pick a color, I can pick a size, hit Draw! and get brightly colored circles. As always, wary that just copying code won't be enough, I decide to expand my options, first by adding in an opacity option, and then thinking "hm, picking from a list of 4-5 colors seems pretty limiting. A color picker of some kind would be an awesome addition."

After a little googling and stack overflowing, I settle on trying react-color, which has a bunch of color pickers to choose from.

What I can't figure out, after about two days of trying, is how to make the color picker interact with the form from the original tutorial, or influence the color of the drawn circle (which defaults to purple, not seeing ANY color choice being made.)

I have no idea how to get a working React app with multiple components running on CodePen, so I can't give a good example of what I have running right now. Here's the relevant bits of code.

Original color/size form (from Controller.js from the tutorial):

export default class Controller extends Component {
  constructor() {
    super();
    this.state = {
      color: "",
      width: "",
      opacity: "", // <- my addition
      toDraw: []
    };
    this.onSubmit = this.onSubmit.bind(this);
    this.onChange = this.onChange.bind(this);
  }

  onSubmit(evt) {
    evt.preventDefault();
    const newShape = {
      color: this.state.color,
      width: this.state.width,
      opacity: this.state.opacity // <- my addition
    };
    this.setState({ toDraw: [...this.state.toDraw, newShape] });
  }

  onChange(evt) {
    this.setState({
      [evt.target.name]: evt.target.value
    });
  }

  render() {
    return (
      <div className="controller">
        <form onSubmit={this.onSubmit}>
          <select name="color" onChange={this.onChange}>
            <option disabled selected="selected" value="">
              {" "}
              Color{" "}
            </option>
            <option value="red"> Red </option>
            <option value="orange"> Orange </option>
            <option value="yellow"> Yellow </option>
            <option value="green"> Green </option>
            <option value="blue"> Blue </option>
            <option value="purple"> Purple </option>
          </select>
          <label> How big: </label>
          <input name="width" onChange={this.onChange} />
          <button type="submit"> Draw! </button>
        </form>
        {this.state.toDraw.length ? <Viz shapes={this.state.toDraw} /> : null}
      </div>
    );
  }
}

(In my code, there's a few more lines, based on the color selection, for choosing opacity. That's working, so I'm leaving it out for now.)

The initial code for the color picker looks like this, where choosing a new color changes the color of the button itself:

import React from "react";
import reactCSS from "reactcss";
import { SketchPicker } from "react-color";

class SketchExample extends Reacht.Component {
  state = {
    displayColorPicker: false,
    color: {
      r: "241",
      g: "112",
      b: "19",
      a: "1"
    }
  };

  handleClick = () => {
    this.setState({ displayColorPicker: !this.state.displayColorPicker });
  };

  handleClose = () => {
    this.setState({ displayColorPicker: false });
  };

  handleChange = color => {
    this.setState({ color: color.rgb });
  };

  render() {
    const styles = reactCSS({
      default: {
        color: {
          width: "36px",
          height: "14px",
          borderRadius: "2px",
          background: `rgba(${this.state.color.r}, ${this.state.color.g}, ${
            this.state.color.b
          }, ${this.state.color.a})`
        },
        swatch: {
          padding: "5px",
          background: "#fff",
          borderRadius: "1px",
          boxShadow: "0 0 0 1px rgba(0,0,0,.1)",
          display: "inline-block",
          cursor: "pointer"
        },
        popover: {
          position: "absolute",
          zIndex: "2"
        },
        cover: {
          position: "fixed",
          top: "0px",
          right: "0px",
          bottom: "0px",
          left: "0px"
        }
      }
    });

    return (
      <div>
        <div style={styles.swatch} onClick={this.handleClick}>
          <div style={styles.color} />
        </div>
        {this.state.displayColorPicker ? (
          <div style={styles.popover}>
            <div style={styles.cover} onClick={this.handleClose} />
            <SketchPicker
              color={this.state.color}
              onChange={this.handleChange}
            />
          </div>
        ) : null}
      </div>
    );
  }
}

export default SketchExample;

Now, I can script kiddy that into my code, import SketchExample into my Controller.js code, and get a nice color-changing button to show up in the middle of my form... but how do I make it change both the color of the button (delightful feedback) AND actually modify the color being chosen for the circles? I have no doubt its a single line (or even just an addition)... but I am stumped as to the where and why.

When I try modifying any of the onChange code in SketchExample.js, the button/color-picker will either stop responding or reset to its initial color when I make any other changes to the form, so clearly there's already some interaction, good or bad... Do I have to modify THAT component, or is it something in the form (other than commenting out the original hand-coded options) itself, or Controller.js, that needs to be updated to handle the output from SketchExample.js?

For reference, I did do the facebook React Tic-Tac-Toe tutorial... but long enough ago that gazing at THAT code and all of its masterful props/state/hoisting logic isn't ringing any particularly useful bells.

Example with opacity working, but color mocking me

Thanks!

JJJ
  • 32,902
  • 20
  • 89
  • 102
Dustin Kreidler
  • 168
  • 1
  • 9

0 Answers0