I have a Sudoku solver project in react. And I want to style it with react or css. I tried both ways and ended up in a confusion. The grid component is my main component and I want to style the board like this:
And here is my simple CSS code
.odd { background-color: gray; }
And my Grid.jsx
import React, { useEffect } from 'react' import '../App.css'; export default function Grid() { // for every input make sure only one number per an input field can be entered const checkInput = (e) => { if (e.target.value.length > 1) { e.target.value = e.target.value.slice(0, 1) } } // Driver function for the grid const grid = document.querySelectorAll('.grid input') useEffect(() => { grid.forEach(item => { item.addEventListener('input', checkInput) }) return () => { grid.forEach(item => { item.removeEventListener('input', checkInput) }) } }, [grid]) // styling for grid element useEffect(() => { const colorChanger = () => { grid.forEach((item, i) => { if ( ((i % 9 === 0 || i % 9 === 1 || i % 9 === 2) && i < 21) || ((i % 9 === 6 || i % 9 === 7 || i % 9 === 8) && i < 27) || ((i % 9 === 3 || i % 9 === 4 || i % 9 === 5) && (i > 27 && i < 53)) || ((i % 9 === 0 || i % 9 === 1 || i % 9 === 2) && i > 53) || ((i % 9 === 6 || i % 9 === 7 || i % 9 === 8) && i > 53) ) { item.classList.add('odd') } }) } colorChanger() }, [grid]) return ( <div className='grid'> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> <input type="number" min='1' max='9' /> </div> ) } <!-- language: lang-html --> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
So how can I achieve the same result in the picture ?
Advertisement
Answer
I suggest you to use a more standard React approach, which is to use Composition. Basically in your Grid you have cells, which is the smallest Component, then you have 9 Squares, which are subunits of 9 cells.
This is a perfect example of composition:
const useEffect = React.useEffect const useState = React.useState const cells = Array(9) .fill("") .map((el, i) => i); const squares = [...cells] const Cell = () => { const [val, setVal] = useState(1); const onChange = (e) => setVal(+e.target.value); return ( <input className="cell" type="number" min="1" max="9" onChange={onChange} value={val} /> ); }; const Square = ({ type }) => ( <div className={`square ${type}`}> {cells.map((c) => ( <Cell key={c} /> ))} </div> ); const Grid = () => ( <div className="grid"> {squares.map((el, i) => ( <Square key={el} type={i % 2 !== 0 ? "light" : "dark"} /> ))} </div> ); ReactDOM.render(<Grid />, document.getElementById("root"))
.grid { width: 396px; height: 396px; } .cell { width:40px; height:40px; padding:0; background:none; } .square { display:inline-block; width: 132px; height: 132px; margin:0; padding:0; } .dark { background: gray; }
<div id="root"></div> <script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script> <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>