React

by michaelnicol

HTML

<div id="app"></div>

CSS

body {
  background: #20262E;
  padding: 20px;
  font-family: Helvetica;
}

#app {
  background: #fff;
  border-radius: 4px;
  padding: 20px;
  transition: all 0.2s;
}

li {
  margin: 8px 0;
}

h2 {
  font-weight: bold;
  margin-bottom: 15px;
}

.done {
  color: rgba(0, 0, 0, 0.3);
  text-decoration: line-through;
}

input {
  margin-right: 5px;
}

React

export const TodoApp = () => {
  const data = useMemo(() => {
    // The data to display will be vertical lines at certian dates.
    return [
      new Date("2022-01-01"),
      new Date("2022-02-01"),
      new Date("2022-03-01"),
      new Date("2022-04-01"),
      new Date("2022-05-01")
    ]
  }, [])
  const svgRef = useRef(null);
  const width = 500
  const height = 500
  useEffect(() => {
    if (svgRef.current) {
      const svg = d3.select(svgRef.current);
      // Remove all SVG
      svg.selectAll("*").remove();
      // Generate the width and domain of the x and y axis.
      // The x-axis will be 500 px wide with a domain of lowest to highest date.
      const xScale = d3.scaleTime().range([0, width]).domain(d3.extent(data));
      // yScale will be a linear scale from 0 to 500 pixels.
      const yScale = d3.scaleLinear().range([height, 0])
      // Create the x-axis
      svg.append("g")
        .attr("transform", `translate(0,${height})`) // Move x-axis to bottom of graph
        .call(
          d3.axisBottom(xScale) // Generate an axis to place tick marks on.
            .ticks(d3.timeMonth.every(1)) // The ticks will be spaced out every month
            .tickFormat((d, i) => { // The text for each tick will be the month name
              if (d instanceof Date) {
                return d3.timeFormat("%B")(d)
              } else {
                return "" + d
              }
            }))
      // Generate the y-axis, no ticks.
      svg.append("g").call(d3.axisLeft(yScale))
    }
  }, [data])

  return (
      {<svg
        ref={svgRef}
        width={width}
        height={height}
      />}
  )
}

ReactDOM.render(<TodoApp />, document.querySelector("#app"))