gaearon / react-hot-loader

Tweak React components in real time. (Deprecated: use Fast Refresh instead.)
http://gaearon.github.io/react-hot-loader/
MIT License
12.26k stars 801 forks source link

Not reload with React.memo and defaultProps #1321

Open joacub opened 5 years ago

joacub commented 5 years ago

When we use React.memo(compoennt) and we set component.defaultProps = {} Hot reloading docent work if we remove component.defaultProps = {}, works

joacub commented 5 years ago
function updateMemoComponent(current$$1, workInProgress, Component, nextProps, updateExpirationTime, renderExpirationTime) {
  if (current$$1 === null) {
    var type = Component.type;
    if (isSimpleFunctionComponent(type) && Component.compare === null **&&
    // SimpleMemoComponent codepath doesn't resolve outer props either.
    Component.defaultProps === undefined**) {
      var resolvedType = type;
      {
        resolvedType = resolveFunctionForHotReloading(type);
      }
      // If this is a plain function component without default props,
      // and with only the default shallow comparison, we upgrade it
      // to a SimpleMemoComponent to allow fast path updates.
      workInProgress.tag = SimpleMemoComponent;
      workInProgress.type = resolvedType;
      {
        validateFunctionComponentInDev(workInProgress, type);
      }
      return updateSimpleMemoComponent(current$$1, workInProgress, resolvedType, nextProps, updateExpirationTime, renderExpirationTime);
    }
    {
      var innerPropTypes = type.propTypes;
      if (innerPropTypes) {
        // Inner memo component props aren't currently validated in createElement.
        // We could move it there, but we'd still need this for lazy code path.
        checkPropTypes(innerPropTypes, nextProps, // Resolved props
        'prop', getComponentName(type), getCurrentFiberStackInDev);
      }
    }
    var child = createFiberFromTypeAndProps(Component.type, null, nextProps, null, workInProgress.mode, renderExpirationTime);
    child.ref = workInProgress.ref;
    child.return = workInProgress;
    workInProgress.child = child;
    return child;
  }
  {
    var _type = Component.type;
    var _innerPropTypes = _type.propTypes;
    if (_innerPropTypes) {
      // Inner memo component props aren't currently validated in createElement.
      // We could move it there, but we'd still need this for lazy code path.
      checkPropTypes(_innerPropTypes, nextProps, // Resolved props
      'prop', getComponentName(_type), getCurrentFiberStackInDev);
    }
  }
  var currentChild = current$$1.child; // This is always exactly one child
  if (updateExpirationTime < renderExpirationTime) {
    // This will be the props with resolved defaultProps,
    // unlike current.memoizedProps which will be the unresolved ones.
    var prevProps = currentChild.memoizedProps;
    // Default to shallow comparison
    var compare = Component.compare;
    compare = compare !== null ? compare : shallowEqual;
    if (compare(prevProps, nextProps) && current$$1.ref === workInProgress.ref) {
      return bailoutOnAlreadyFinishedWork(current$$1, workInProgress, renderExpirationTime);
    }
  }
  // React DevTools reads this flag.
  workInProgress.effectTag |= PerformedWork;
  var newChild = createWorkInProgress(currentChild, nextProps, renderExpirationTime);
  newChild.ref = workInProgress.ref;
  newChild.return = workInProgress;
  workInProgress.child = newChild;
  return newChild;
}

the problem its here, if I remove this condition

&&
    // SimpleMemoComponent codepath doesn't resolve outer props either.
    Component.defaultProps === undefined

All works fine.

theKashey commented 5 years ago

That's actually React code, we have no power* upon it. And it seems to me that memo is not working with defaultProps at all - just ignores them.

joacub commented 5 years ago

That’s it’s on @hot-loader/react-dom, if you remove the condition work fine

joacub commented 5 years ago

The thing is simple if not exits defaultprops definition on the component works perfect so on the patcher kill the condition

theKashey commented 5 years ago

@hot-loader/react-dom is react-dom. We landed a few patches to it, but that's all. React 16.9.0 already contain another interface for making things hot, and we try to remove our patches, not adding more.

And if React own hot loading is not working with .defaultProps set, then it's up to future versions of React to fix. Ie it should be already broken for React.Native.

joacub commented 5 years ago

@theKashey so , no solutions for this ?

theKashey commented 5 years ago

Why do you need default Props on memo?

joacub commented 5 years ago

The default props it’s declared on the component

Const MyButton = React.memo(() = { return something; }) MyButton.propTypes = { Name: PropType.string }

MyButton.defaultProps = { Name: ‘My default name’ }

joacub commented 5 years ago

How you see above, if the component has fails hot, if not works

worapolburaphan commented 4 years ago

The default props it’s declared on the component

Const MyButton = React.memo(() => { return something; }) MyButton.propTypes = { Name: PropType.string }

MyButton.defaultProps = { Name: ‘My default name’ }

You can try this solution

Const MyButton =() => {
return something;
})
MyButton.propTypes = {
Name: PropType.string
}

MyButton.defaultProps = {
Name: ‘My default name’
}
export default React.memo(MyButton)