preactjs / signals

Manage state with style in every framework
https://preactjs.com/blog/introducing-signals/
MIT License
3.79k stars 93 forks source link

Show / not show component content #305

Closed homerokzam closed 1 year ago

homerokzam commented 1 year ago

How do I change a "state" to show or not show component content?

Ex:

import { useSignal } from "@preact/signals-react";
import { Button } from '@mui/material';
import './App.css';

const Display = ({open}) => {
  console.log(`render <Display /> with open=${open}`);
  return (
    <div>
      {open &&
        <div>
          SHOW
        </div>
      }
    </div>
  )
}

const App = () =>{
  const countA = useSignal(0);
  const countB = useSignal(0);
  const open = useSignal(false);

  const handleOpen = () => open.value = !open.value;

  console.log("render");
  console.log(open.value);

  return (
    <div>
      <Button onClick={() => countA.value++}>countA: {countA}</Button>
      <br />
      <Button onClick={() => countB.value++}>countA: {countB}</Button>
      <br />
      <Button variant="contained" onClick={handleOpen}>{open ? 'Show' : 'Close'}</Button>
      <br />
      <Display open={open.value} />
    </div>
  )
}

export default App;

Thanks.

rschristian commented 1 year ago

Probably a duplicate of #298. Try downgrading to v1.1.1, that should help.

<Button variant="contained" onClick={handleOpen}>{open ? 'Show' : 'Close'}</Button>

Unrelated, but this probably is a bug. Signals are objects, and objects are truthy, so 'Show' will always be shown. You want the following instead:

<Button variant="contained" onClick={handleOpen}>{open.value ? 'Close' : 'Show'</Button>

I imagine you want the strings to be reversed too, showing 'Close' when the display is open, and 'Show' when it's hidden.

homerokzam commented 1 year ago

Thank you very much for your answer.

I really had an error of mine in the "... onClick={handleOpen}>{open ..." part. The correct way would be to use open.value, but it still has the same behavior.

I downgraded it, but the behavior remained the same as with useState. Every component was rendered.

Thanks

rschristian commented 1 year ago

I downgraded it, but the behavior remained the same as with useState. Every component was rendered.

That's correct, if you're using React. Only text nodes (countA & countB, from above) get to skip full component rerenders if you're using React.

I'll close this out as a duplicate, but feel free to reply if you're still having issues.