Next.js Discord

Discord Forum

Component is not updated using useState

Unanswered
.doodeedoo posted this in #help-forum
Open in Discord
Trying out a basic example. I'm new at NextJS, so it might be something really simple.

I've removed the non-important lines. I just want to click on a button, and a component should update it's value. The correct number is shown in a alert box, so don't focus on the missing code, it's working fine up until the alert.

What am I doing wrong / missing?

TYIA!

export default async function Page(pageProps: PageProps) {
const [selectedLabel, setSelectedLabel] = useState("");

function showLabel(LID: string) {
alert("setSelectedLabel = " + LID);

setSelectedLabel(LID);
}

....

return (

....

<button onClick={() => showLabel(aLabel.l.properties.LID.toString())}>Show label</button>

<LabelComponent LID={selectedLabel} />

...
} // end of page

Here is LabelComponent;

interface ComponentProps {
LID: string;
}

const LabelComponent = (props: ComponentProps) => {
return (
<div>
<h1>{props.LID}</h1>
</div>
)
}

export default LabelComponent;

15 Replies

can you post your code using code block and sytax highlihgting like this

```js
paste code here
```
export default async function Page(pageProps: PageProps) {
  const [selectedLabel, setSelectedLabel] = useState("");

  function showLabel(LID: string) {
    alert("setSelectedLabel = " + LID);

    setSelectedLabel(LID);
  }

   ....

return (

   ....

<button onClick={() => showLabel(aLabel.l.properties.LID.toString())}>Show label</button>

<LabelComponent LID={selectedLabel} />

...
} // end of page

Here is LabelComponent;

interface ComponentProps {
  LID: string;
}

const LabelComponent = (props: ComponentProps) => {
  return (
    <div>
      <h1>{props.LID}</h1>
    </div>
  )
}

export default LabelComponent;
try
  function showLabel(LID: string) {
    alert("setSelectedLabel = " + LID);
    console.log("value: "+LID)
    setSelectedLabel(LID);
  }
The conole output is the same as in the alert box ("3").
@.doodeedoo The conole output is the same as in the alert box ("3").
have you tried creating a client component for that? instead of doing in a page component which is supposed to be server only,
I've this statement in the top of the file, I've read it should work. I only tried different things inside this file.

'use client';
I mean in the top of page.tsx
Also, I don't really know how to do what you ask. I thought the whole point with useState is that it automagically detects what parts of the page / components to re-evaluate...?
you're not supposed to do 'use client' on page component
create a child component that uses 'use client' and put useState there
Ok, I refactored the code below. It's the exact same result. The ID is being written to the console, but the html is not updated.

import PageProps from "../../../types/PageProps";
import LabelTable from "../../../components/LabelTable";

export default async function Page(pageProps: PageProps) {
  return (
    <div>
      <LabelTable />
    </div>
  );
}

---------------------

'use client';

interface ComponentProps {
  LID: string;
}

const LabelComponent = (props: ComponentProps) => {
  return (
    <h1>{props.LID}</h1>
  )
}

export default LabelComponent;
'use client';

import { Integer, Node } from "neo4j-driver";
import { useState } from "react";
import LabelProperties from "../types/properties/LabelProperties";
import { LABELLED } from "../types/relationships/LABELLED";
import ProductProperties from "../types/properties/ProductPropeties";
import { read } from "../lib/neo4j";
import LabelComponent from "./LabelComponent";

type PageResult = {
    l: Node<Integer, LabelProperties>;
    r: LABELLED;
    p: Node<Integer, ProductProperties>;
}

const LabelTable = async () => {
    const [selectedLabel, setSelectedLabel] = useState("");

    function showLabel(LID: string) {
        console.log("ID: " + LID);

        setSelectedLabel(LID);
    }

    const result = await read<PageResult>(
        `
      MATCH (p:Product {SKU : 'ID-00092'})-[r:LABELLED]->(l:Label)
      RETURN r, l, p
      ORDER BY r.created
      `
    );

    return (
        <table width="100%">
            <thead></thead>
            <tbody>
                <tr>
                    <td>
                        <ul>
                            {result.map((aLabel) => (
                                <li key={aLabel.l.properties.LID.toString()}>
                                    <button onClick={() => showLabel(aLabel.l.properties.LID.toString())}>Show label</button>
                                    <span>{aLabel.r.properties.created.toString()} (ID: {aLabel.l.properties.LID.toString()})</span>
                                </li>
                            ))}
                        </ul>
                    </td>
                    <td>
                        <LabelComponent LID={selectedLabel} />
                    </td>
                </tr>
            </tbody>
        </table>
    )
}

export default LabelTable;
client component can't be async @.doodeedoo
Ok - solved it by making the page query the db, setting the data as a prop on a client component. It would have been helpful to have gotten warnings on;

my attempt at using async on the client component
my attempt at using 'use client' on a page

Thanks for the pointers @alfon 👍
no problem, yeah the error log could be better haha