Back to List

Building an Experiment Dashboard with React

Learn React components, Props, and State through bio examples. Build gene cards, sample lists, and experiment dashboards to understand React fundamentals.

Beginner
|
75min
|
Verified (2026-06)
ReactComponentPropsStateJSXUI Framework
Progress0/19 (0%)

Building an Experiment Dashboard with React

So far you've built structure with HTML, added behavior with JavaScript, created servers with Node.js and Express, and completed APIs that store and retrieve experiment data from databases. But as screens grow complex, problems arise. Gene info cards, sample lists, QC result tables, filter buttons โ€” managing all of this in a single HTML file with innerHTML quickly leads to thousands of lines of code.

React solves this problem. It's the technology for creating your own custom HTML tags. Instead of basic tags like <div> or <span>, you create meaningful tags like <GeneCard>, <SampleList>, <QcDashboard>. Just as labs break down complex procedures into protocol units for management, React breaks down UI into component units.

Components: Creating Custom Tags

Components are the core of React. One function = one tag:

javascript
function GeneCard() {
  return (
    <div>
      <h3>TP53</h3>
      <p>Chromosome: 17p13.1</p>
      <p>Function: tumor suppressor</p>
    </div>
  );
}

Once you create this function, you can use it as a <GeneCard /> tag. It must start with an uppercase letter โ€” React uses lowercase for regular HTML tags and uppercase for user-created components.

Combine multiple components to build the full screen:

javascript
function App() {
  return (
    <div>
      <Header />
      <GeneCard />
      <SampleList />
    </div>
  );
}

Looking at the App function alone, you can tell in one second that this screen consists of Header, GeneCard, and SampleList. Complex HTML is hidden behind meaningful names.

Three benefits of components:

  • Readability: The code structure is visible at a glance
  • Reusability: If you need <GeneCard /> in 10 places, just use it 10 times
  • Maintainability: To change the card design, modify the GeneCard function in one place and all cards update simultaneously

Props: Passing Data to Components

The GeneCard above always shows TP53. To show other genes, use Props (short for Properties). Same concept as function parameters:

javascript
function GeneCard(props) {
  return (
    <div>
      <h3>{props.name}</h3>
      <p>Chromosome: {props.chromosome}</p>
      <p>Function: {props.geneFunction}</p>
    </div>
  );
}

function App() {
  return (
    <div>
      <GeneCard name="TP53" chromosome="17p13.1" geneFunction="tumor suppressor" />
      <GeneCard name="BRCA1" chromosome="17q21.31" geneFunction="DNA repair" />
      <GeneCard name="EGFR" chromosome="7p11.2" geneFunction="receptor tyrosine kinase" />
    </div>
  );
}

In <GeneCard name="TP53" chromosome="17p13.1" />, name, chromosome, and geneFunction are Props. React bundles these values into one object and passes it as the function's first parameter (props).

In JSX, curly braces {} mean "this is JavaScript territory." Writing {props.name} outputs the name value from the props object. Writing props.name without braces would literally display the text "props.name" on screen.

In lab terms โ€” GeneCard is the protocol template, and Props are the samples you plug into it. Same protocol, but different results depending on the sample (data).

List Rendering: Arrays to Components

If you have 100 samples instead of 3, you can't write <GeneCard /> 100 times. Process array data with a loop:

javascript
function SampleList(props) {
  const items = [];

  for (let i = 0; i < props.samples.length; i++) {
    const sample = props.samples[i];
    items.push(
      <li key={sample.id}>
        {sample.id}: OD={sample.od} โ€” {sample.status}
      </li>
    );
  }

  return (
    <ul>{items}</ul>
  );
}

function App() {
  const sampleData = [
    { id: "S001", od: 1.85, status: "pass" },
    { id: "S002", od: 0.42, status: "fail" },
    { id: "S003", od: 2.10, status: "pass" }
  ];

  return (
    <div>
      <h2>Sample QC Results</h2>
      <SampleList samples={sampleData} />
    </div>
  );
}

A few notes:

  • key={sample.id} โ€” elements created by loops must have a unique key. React uses it to track which items changed. Like assigning a unique ID to each lab sample.
  • samples={sampleData} โ€” when passing arrays as Props, wrap with curly braces. Strings use quotes, JavaScript values (arrays, numbers, variables) use curly braces.

State: Managing Changing Data

Props are values received from outside and can't be changed inside the component. Like not being allowed to modify experiment conditions written on a protocol mid-way. But experiment progress status keeps changing โ€” "pending" โ†’ "in progress" โ†’ "complete." State manages this internal status.

javascript
function ExperimentTracker() {
  const [status, setStatus] = React.useState("Pending");
  const [count, setCount] = React.useState(0);

  function handleStart() {
    setStatus("In Progress");
    setCount(count + 1);
  }

  function handleComplete() {
    setStatus("Complete");
  }

  return (
    <div>
      <p>Experiment status: {status}</p>
      <p>Run count: {count}</p>
      <button onClick={handleStart}>Start Experiment</button>
      <button onClick={handleComplete}>Complete Experiment</button>
    </div>
  );
}

React.useState("Pending") returns two things:

  • status โ€” current value ("Pending")
  • setStatus โ€” function to change the value

Calling setStatus("In Progress") changes status, and React automatically re-renders the screen. No need to manually manipulate DOM with innerHTML โ€” just change State and the screen updates itself. This is React's biggest advantage.

PropsState
DirectionComes from outsideManaged internally
ModifiableNo (read-only)Yes (setState)
AnalogyExperiment conditions on a protocolExperiment progress status
ExampleGene name, chromosome location"Pending" โ†’ "In Progress" โ†’ "Complete"

Full Example: QC Dashboard

Combining components, Props, and State, you can build a simple QC dashboard:

javascript
function QcResult(props) {
  const style = {
    color: props.passed ? "green" : "red",
    fontWeight: "bold"
  };

  return (
    <tr>
      <td>{props.sampleId}</td>
      <td>{props.od}</td>
      <td style={style}>{props.passed ? "PASS" : "FAIL"}</td>
    </tr>
  );
}

function QcDashboard() {
  const samples = [
    { id: "S001", od: 1.85, passed: true },
    { id: "S002", od: 0.42, passed: false },
    { id: "S003", od: 2.10, passed: true },
    { id: "S004", od: 0.15, passed: false }
  ];

  const passCount = samples.filter(function(s) { return s.passed; }).length;

  return (
    <div>
      <h2>QC Dashboard</h2>
      <p>Passed: {passCount} / {samples.length}</p>
      <table>
        <thead>
          <tr><th>Sample ID</th><th>OD</th><th>Result</th></tr>
        </thead>
        <tbody>
          {samples.map(function(s) {
            return <QcResult key={s.id} sampleId={s.id} od={s.od} passed={s.passed} />;
          })}
        </tbody>
      </table>
    </div>
  );
}

QcResult shows results for a single sample, QcDashboard wraps the whole thing. Even if data grows to 100 items, the QcResult component doesn't need a single change โ€” just add more data.

Try It Yourself (Faded Example)

Fill in the blanks to complete a React component that displays gene information.

Fill in the Blanksjavascript
function GeneInfo() {
return (
<div>
<h3>{props.}</h3>
<p>Length: {.length_bp} bp</p>
</div>
);
}
// Usage: <GeneInfo name="TP53" length_bp={19149} />

Common Errors & Solutions

Q: Component doesn't appear on screen

If the component name starts with lowercase, React treats it as a regular HTML tag. Change geneCard โ†’ GeneCard โ€” capitalize the first letter.

Q: Each child in a list should have a unique "key" prop warning

Elements created by loops are missing a key prop. Assign a unique value (ID, sample number, etc.) from each array item as key. Using the index (i) as key is not recommended.

Q: Confused about when to use curly braces vs quotes

Strings use quotes: name="TP53". Numbers, arrays, variables, and other JavaScript values use curly braces: count={42}, data={myArray}. To execute JavaScript code inside JSX, wrap it in curly braces: {props.name}.

Q: Changed State directly but screen didn't update

Changing values directly like status = "Complete" prevents React from detecting the change. You must use the setter function like setStatus("Complete") for React to re-render the screen.

๐Ÿ’ฌ Questions & Comments

0 comments

You can post without signing in. Guest comments cannot be edited or deleted by their author.

0/2000

Loading...