preactjs / preact-router

:earth_americas: URL router for Preact.
http://npm.im/preact-router
MIT License
1.01k stars 156 forks source link

Router is re-using DOM elements, how could I force a new one? #192

Open mattdesl opened 7 years ago

mattdesl commented 7 years ago

Hi there — in our code we tend to apply CSS to a component on componentDidMount (specifically, using GSAP for complex animations).

However, when routing around I've noticed that preact-router (or preact itself?) likes to hold onto DOM nodes where possible, rather than creating a new one. This mutability forces us to write code that always resets the CSS state of a component on mount.

Here is an example; where the style is set on mount, and when re-routing to that component the style will already have been set from the previous route change.

Or am I misunderstanding the way preact/vdom works? Is there a way to force the re-creation of a DOM element so I can mutate its styles/etc without concern for how it will break future mounting?

import Router, { Link } from 'preact-router';
import { h, render, Component } from 'preact';

class TestComponent extends Component {

  componentDidMount () {
    if (this.base.style.padding) {
      console.error('Padding is already set...', this.base.style.padding);
    }
    this.base.style.padding = '20px';
  }

  render () {
    return <div />
  }
}

class About extends Component {

  render () {
    return <div>About</div>
  }
}

class App extends Component {

  render () {
    return <div>
      <Link href="/">TestComponent</Link>..
      <Link href="/about">About</Link>
      <Router>
        <TestComponent path="/" default />
        <About path="/about" />
      </Router>
    </div>
  }
}

render(<App />, document.body);
developit commented 7 years ago

Hi there - if you add unique key properties to the children of router, it will always unmount and mount:

class App extends Component {

  render () {
    return <div>
      <Link href="/">TestComponent</Link>..
      <Link href="/about">About</Link>
      <Router>
        <TestComponent key="test" path="/" default />
        <About key="about" path="/about" />
      </Router>
    </div>
  }
}
Kiarash-Z commented 6 years ago

same here