Skip to content
    SeaCode
    Learning tracksCode ArenaWorkshops & EventsInstructors
    Log inSign up
    ⚛React

    Components and JSX

    • Why React?
    • JSX rules
    • Props
    • Rendering lists and keys
    • Conditional rendering

    State and events

    • Handling events
    • useState: a component's memory
    • Objects and arrays in state
    • Forms and controlled inputs
    • Lifting state up

    Effects and essential hooks

    • useEffect
    • Fetching data
    • useRef
    • Context: data for the whole tree
    • useReducer

    Professional React

    • Writing your own hooks
    • Performance: memo, useMemo and useCallback
    • Suspense and error boundaries
    • What's new in React 19
    • Thinking in React
    • Project: a complete to-do app
    React

    Professional React · Lesson 20 of 21

    Thinking in React

    From a design to components: split, build static, find minimal state, place it.

    9 minutes2 games

    Before writing code, follow the steps the React team recommends:

    1. Break the design into components: each thing that does one job. 2. Build a static version with props only, no state. 3. Find the minimal state: for each value ask: does it change? If so, can it be computed from something else? 4. Decide where each piece of state lives: the closest common parent of everything that needs it. 5. Add inverse data flow: children call the parent's functions.

    • CourseCatalog (state: query, onlyFree)
      • SearchBar (query, onlyFree, onChange…)
      • CourseTable (courses, query, onlyFree)
        • TrackRow (track name)
        • CourseRow (one course)

    A course catalogue page after splitting it.

    React
    const COURSES = [
      { track: "Web", title: "HTML & CSS", price: 0 },
      { track: "Web", title: "JavaScript", price: 450 },
      { track: "Web", title: "React", price: 600 },
      { track: "Data", title: "Python", price: 400 },
      { track: "Data", title: "SQL", price: 300 },
    ]
    
    function SearchBar({ query, onlyFree, onQuery, onOnlyFree }) {
      return (
        <div>
          <input value={query} onChange={(e) => onQuery(e.target.value)} placeholder="Search…" />
          <label><input type="checkbox" checked={onlyFree} onChange={(e) => onOnlyFree(e.target.checked)} /> Free only</label>
        </div>
      )
    }
    
    function CourseTable({ courses, query, onlyFree }) {
      const visible = courses.filter((c) => c.title.toLowerCase().includes(query.toLowerCase()) && (!onlyFree || c.price === 0))
      const tracks = [...new Set(visible.map((c) => c.track))]
      if (visible.length === 0) return <p>No courses match.</p>
      return (
        <table>
          <tbody>
            {tracks.map((t) => (
              <Fragment key={t}>
                <tr><th colSpan={2} style={{ textAlign: "start" }}>{t}</th></tr>
                {visible.filter((c) => c.track === t).map((c) => (
                  <tr key={c.title}><td>{c.title}</td><td>{c.price || "Free"}</td></tr>
                ))}
              </Fragment>
            ))}
          </tbody>
        </table>
      )
    }
    
    function App() {
      const [query, setQuery] = useState("")
      const [onlyFree, setOnlyFree] = useState(false)
      return (
        <div>
          <SearchBar query={query} onlyFree={onlyFree} onQuery={setQuery} onOnlyFree={setOnlyFree} />
          <CourseTable courses={COURSES} query={query} onlyFree={onlyFree} />
        </div>
      )
    }

    Important

    This example has just two pieces of state: query and onlyFree. The filtered list isn't state; it's computed from them. The courses never change, so they're props. Less state means fewer bugs, since there are no copies to fall out of sync.

    Quick question

    On a cart page, which value should not be state?

    Interview question

    You're given a page design. How do you split it into components?

    Exercise

    This search is case-sensitive, so typing java doesn't find JavaScript. Fix it. The checker types java, and only Web JavaScript 450 should show.

    The page should show: Web JavaScript 450

    React
    const COURSES = [
      { track: "Web", title: "HTML & CSS", price: 0 },
      { track: "Web", title: "JavaScript", price: 450 },
      { track: "Data", title: "Python", price: 400 },
    ]
    
    function App() {
      const [query, setQuery] = useState("")
      const visible = COURSES.filter((c) => c.title.includes(query))
      return (
        <div>
          <input value={query} onChange={(e) => setQuery(e.target.value)} />
          <ul>
            {visible.map((c) => <li key={c.title}>{c.track} {c.title} {c.price}</li>)}
          </ul>
        </div>
      )
    }

    Learn more from

    • react.dev: Thinking in Reactreact.dev
    • react.dev: Choosing the state structurereact.dev
    • Wikipedia: Single-responsibility principleen.wikipedia.org

    Played 0 of 2 games

    Sign in to save your progress and earn XP.

    PreviousWhat's new in React 19NextProject: a complete to-do app
    SeaCode

    Learn to code for real, online or at our branch in front of Cairo University, Giza.

    Learn

    • All courses
    • Interactive tutorials
    • Interview practice problems
    • Mock interview
    • Learning tracks
    • Code Arena
    • Workshops & Events
    • Knowledge library
    • Team projects

    Your account

    • Log in
    • Sign up
    • Learning plan
    • Certificates
    • Site map

    Contact us

    • WhatsApp
    • 010 9094 1104
    • In front of Cairo University, Giza

    © 2026 SeaCode. All rights reserved.