question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Using extended classes for props doesn't get picked up by react-refresh

See original GitHub issue

I have a curious case where I am using classes instead of plain old JS objects as input properties for my components.

Simple usage with classes like the following works as expected and maintains its state when I make changes to styling etc.

import { createElement, useState } from 'react' 
 
export class CounterProps {
    constructor(title) {
        this.title = title;
    }
}

export const Counter = (props) => {
  const [count, setCount] = useState(0)
  return createElement("div", null, 
    createElement("h1", null, props.title),
    createElement("h1", null, count), 
    createElement("button", { onClick: () => setCount(count + 1) }, "Increment")
  );
}

export const Counters = () => {
  return createElement("div", null, 
     createElement(Counter, new CounterProps("Page title")),
     createElement(Counter, new CounterProps("Another title"))
   );
}

However, once I extend CounterProps with anything then fast-refresh doesn’t pick up the changes anymore:

export class Anything { }

export class CounterProps extends Anything {
    constructor(title) {
        super();
        this.title = title;
    }
}

I am using the following versions (on Windows):

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:2
  • Comments:22 (7 by maintainers)

github_iconTop GitHub Comments

4reactions
Zaid-Ajajcommented, Dec 15, 2020

I don’t know why you’re doing this

@gaearon The reason is simple: this is how F# records are compiled to JavaScript using Fable and these F# records happen to be a really nice way to define lightweight React component prop types:

type NavigationItemProps = {
    title: string
    active : bool
}

// Component defition
[<ReactComponent>]
let NavigationItem (props: NavigationItemProps) = 
  let (hovered, setHovered) = React.useState(props.active)
  Html.h1 props.title

// call-site: 
NavigationItem { title = "Home"; active = false }

There are workarounds of course but I would really appreciate it if we could define React components in F# the following structure: F# source file is called {ComponentName}.fs and contains the props type definition along with the function itself. Potentially having multiple small components and their prop types in the same file when you have small components.

2reactions
Zaid-Ajajcommented, Dec 15, 2020

Hi @pmmmwh, first of all, thanks a lot for the detailed answer. I now understand why the refresh fails. However, from the perspective of the F# side of things (because I am really talking about JS which is transpiled from F#), it could be possible to add metadata to the class declaration which could very well easily allow fast-refresh to pick it up. Two questions arise:

  • Which metadata do you need? It could be a dummy, compiler-generated function with a special name like $IamClass which will be returned in the property names array when you ask Object.getOwnPropertyNames(Test.prototype) => ["constructor", "$IamClass"]

  • How to generically tell or hint the plugin that with that information? An option passed to the plugin would do the trick { classDetectionHints: ["$IamClass"] } or something similar.

What do you think?

Read more comments on GitHub >

github_iconTop Results From Across the Web

React.Component
Use shouldComponentUpdate() to let React know if a component's output is not affected by the current change in state or props. The default...
Read more >
React: why child component doesn't update when prop changes
Update the child to have the attribute 'key' equal to the name. The component will re-render every time the key changes.
Read more >
How To Manage State on React Class Components
To update state , React developers use a special method called setState that is inherited from the base Component class. The setState method...
Read more >
React Class Components - W3Schools
Props. Another way of handling component properties is by using props . · Props in the Constructor. If your component has a constructor...
Read more >
Why hooks are the best thing to happen to React
Originally, React mainly used class components, which can be strenuous ... export default class Hello extends Component { constructor(props) ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found