wufe / react-particles-js

Particles.js for React
https://rpj.bembi.dev/
MIT License
1.15k stars 106 forks source link

Particles re-renders on every state change even when it is separate from all the state changes. #43

Closed Here2Huynh closed 6 years ago

Here2Huynh commented 6 years ago

I wrapper all the components that have state changes into a wrapper but the Particles component still gets re-rendered on changes.

 render() {
    const { isSignedIn, imageUrl, route, box, user } = this.state;
    return (
      <div className="App">
        <Particles className='particles' params={particlesOptions} />
        <ComponentsWrapper 
          isSignedIn={isSignedIn}
          imageUrl={imageUrl}
          route={route}
          box={box} 
          user={user}
          loadUser={this.loadUser}
          onInputChange={this.onInputChange}
          onImageSubmit={this.onImageSubmit}
          onRouteChange={this.onRouteChange}
        />
      </div>
    );
  }
}
wufe commented 6 years ago

Are particlesOptions or their reference changing? If so, the particles component updates itself.

Here2Huynh commented 6 years ago

No, they are not. It is a const at the top and is predefined.

const particlesOptions = {
  particles: {
    number: {
      value: 30,
      density: {
        enable: true,
        value_area: 800
      }
    }
  },
  interactivity: {
    detect_on: 'window',
    events: {
      onclick: {
        enable: true,
        mode: 'repulse'
      }
    }
  }
} 
wufe commented 6 years ago

Can you try wrapping the Particles element into a Particles container?

Here2Huynh commented 6 years ago

I figured it out. Had to separate the components with state changes into a separate component. Thanks for your time!

wufe commented 6 years ago

You're welcome

r1shank commented 2 years ago

hey @wufe @Here2Huynh ... any chance you could explain how you prevented re-rendering on changing state?

return (
    <Wrapper toggle={props.toggle}>
      <BParticles />
    </Wrapper>
  );
};

toggle is a state that changes.

I did this but it's still re-rendering :/ BParticles is the component inside which I've used the 'react-tsparticles' library. I'm not sure how to prevent re-renders.

Here2Huynh commented 2 years ago

@acnologia I think that state change causes everything to re-render, hence the BParticles is re-rendering too. I recall my situation is similar. I had to quarantine the BParticles and render it when I use it. Perhaps try a ternary expression.

r1shank commented 2 years ago

what is quarantine? how would a ternary help?

In my project, BParticles runs continuously as the background. I'm using it 100% of the time. Anyway I can prevent the re-render?

Here2Huynh commented 2 years ago

I see. I think a ternary expression would help then i.e. props.toggle ? : null

I think the state change of props.toggle is triggering everything to re-render. Depending on your code, you could look for a way to prevent a render in React in a different way.

r1shank commented 2 years ago

yeah it's definitely the toggle state that is making everything re-render. it's the only state that is actively changing right now.

props.toggle ? : null what do you mean by null?

any chance I could share the concerned section of the code with you?

Here2Huynh commented 2 years ago

Sure.

Ternary with null is the React way of conditional re-rendering.

On Tue, Aug 30, 2022 at 7:10 PM acnologia @.***> wrote:

yeah it's definitely the toggle state that is making everything re-render. it's the only state that is actively changing right now.

props.toggle ? : null what do you mean by null?

any chance I could share the concerned section of the code with you?

— Reply to this email directly, view it on GitHub https://github.com/wufe/react-particles-js/issues/43#issuecomment-1232366659, or unsubscribe https://github.com/notifications/unsubscribe-auth/AIUQVKJY3ITAVLBRRYLJQS3V325IZANCNFSM4FD55EMQ . You are receiving this because you were mentioned.Message ID: @.***>

Here2Huynh commented 2 years ago

Or, you can try to memoize the child like this example:

https://stackoverflow.com/questions/54015086/how-to-prevent-child-component-from-re-rendering-when-using-react-hooks-and-memo

On Tue, Aug 30, 2022 at 10:56 PM John Huynh @.***> wrote:

Sure.

Ternary with null is the React way of conditional re-rendering.

On Tue, Aug 30, 2022 at 7:10 PM acnologia @.***> wrote:

yeah it's definitely the toggle state that is making everything re-render. it's the only state that is actively changing right now.

props.toggle ? : null what do you mean by null?

any chance I could share the concerned section of the code with you?

— Reply to this email directly, view it on GitHub https://github.com/wufe/react-particles-js/issues/43#issuecomment-1232366659, or unsubscribe https://github.com/notifications/unsubscribe-auth/AIUQVKJY3ITAVLBRRYLJQS3V325IZANCNFSM4FD55EMQ . You are receiving this because you were mentioned.Message ID: @.***>

r1shank commented 2 years ago

wait i have a question ... my prop is being used in a ternary operator for my tsparticles wrapper. does that make a difference?

Do you have any resources on the ternary method? I understand the mechanics, but I don't understand where to implement it :/

Here2Huynh commented 2 years ago

In that code, you have shown up there. That isn't a ternary operator.

An example of it in React is this: https://dev.to/rthefounding/react-use-a-ternary-expression-for-conditional-rendering-1hmb

It is a pretty popular pattern for conditional rendering in React.

r1shank commented 2 years ago

oh lemme clarify what the prop is used for.

I'm using the prop to add a conditional style on the wrapper. the particles background stays even when the wrapper style is applied. I'm using the wrapper to change margins between the toggle.

does that make sense? I'm not trying to use the prop to say that BParticles should render only if condition is met. I want it to render the full time without re-rendering even if the prop state changes

r1shank commented 2 years ago

i'm using a ternary operator within a styled component.

const Wrapper = styled.div<ToggleProps>`
  margin:  ${props => (props.toggle ? '5px' : '15px')} ;
`;
Here2Huynh commented 2 years ago

oh that should be fine then.

I am still confused on what you want to prevent re-rendering then, but it sounds like either you have to do a custom check in componentDidMount hook or memoize it like the example I pasted above.

r1shank commented 2 years ago

whenever i change the state of toggle ... what is happening is that the BParticles is re-rendering. Is it super evident because the positions of the particles abruptly change and look horrible. that is what I'm trying to prevent.

Was that not the same problem you had? What were you trying to prevent from re-rendering?

Would memoize work for that?

Here2Huynh commented 2 years ago

I see. It is because the Wrapper component is the parent component and that component's state got changed, hence triggering the re-rendering. You are changing the wrapper's (parent) margins, so logically every child of that will re-render.

It is similar. I just separated the components that had state changes and render the particles when I used it. It is not running in the background like yours ( I am assuming).

Yea, I believe memoizing would work for this use case that you absolutely need the toggle prop to change the wrapper's margin.

r1shank commented 2 years ago

alright i'll try in the morning! i'll lyk how it goes!

What was the exact implementation you did?

Here2Huynh commented 2 years ago

Nice, mines just renders the particles on click of a button like congrats you made the right choice kinda scenario.

r1shank commented 2 years ago

Oh that's an interesting use case.

I haven't really tried it yet because there are other features I'm trying to roll out atm, but I'll definitely try by tomorrow and contact you if I run into any road blocks. Thanks again for your help!

atakansavas commented 1 month ago

Or, you can try to memoize the child like this example: https://stackoverflow.com/questions/54015086/how-to-prevent-child-component-from-re-rendering-when-using-react-hooks-and-memo On Tue, Aug 30, 2022 at 10:56 PM John Huynh @.> wrote: Sure. Ternary with null is the React way of conditional re-rendering. On Tue, Aug 30, 2022 at 7:10 PM acnologia @.> wrote: > yeah it's definitely the toggle state that is making everything > re-render. it's the only state that is actively changing right now. > > props.toggle ? : null what do you mean by null? > > any chance I could share the concerned section of the code with you? > > — > Reply to this email directly, view it on GitHub > <#43 (comment)>, > or unsubscribe > https://github.com/notifications/unsubscribe-auth/AIUQVKJY3ITAVLBRRYLJQS3V325IZANCNFSM4FD55EMQ > . > You are receiving this because you were mentioned.Message ID: > @.***> >

This explanation helps me. Thank you, I fixed my issue by using useMemo!