-
Notifications
You must be signed in to change notification settings - Fork 801
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support React 16.3 #918
Comments
Yes, new challenge to come! |
++ we have to test how new ("real") Context API works, as long "Context" is not a "Tag" or a function - it is a brand new element type. Should be fine, but even enzyme itself failing :) |
@oliviertassinari - yeah, RHL is adding componentWillReceiveProps, and I am going just to drop it. |
Had just this issue right now. I am very new to react, just started and had to scratch my head (like a lot) to understand this isn't coming from mine, rather the hot loader 😁 . I will be waiting for an update. |
I don't understand what this means:
|
@gaearon - this is a local meme( #830 ), about performing hot-render each time you "can do it". V3 uses AppContainer to start an update, v4 can use AppContainer to perform sync updates, and Component.render to perform async updates. Async cos they could be executed after the main update or main update could not "render into them" - code splitting, resource load, portals, and so on. Plus we have to defer .forceUpdate, as long shall not call it from a render method. |
What are you using |
Nothing but to being able "flush"(forceUpdate) changes. As I pointed above - we could safely remove it. It may cause double renders, but this is not something we should avoid. |
Got it. |
PS: Is there any "new"(~fiber) way to trigger re-render? Is there any way to re-render SFC without a real Component on top of it? Is there any a bit more "soft" ways to update? |
Can you be more specific? Maybe a small code example? |
Do we have other choice rather then calling .forceUpdate? How do new Context API handle it? |
Isn't that what |
Yep, this is related to |
React maintains a tree of nodes per root. Each node in a tree has an "expiration time" which can either be some time in the future, a marker that says "nothing to do here" or a marker that says "flush it synchronously". When we
React loops over all scheduled roots. That list contains this root (because we just "scheduled" it). React then looks at all its child nodes that have expiration time that is not "nothing to do here", depth first. That's why it goes over each ancestor. It "skips over" the deep parents (before Eventually it gets to the child that actually has something new in the update queue (our node) and that's when it starts re-rendering. I hope this gives some insight into how it works internally. We could expose some of this, or we could keep using hacky internal APIs, or a mix of both. The question is what would be valuable to expose. I don't remember enough about how RHL works to say what would be, but maybe you could tell me? Does this help at all? |
Look like we still have to use forceUpdate to mark node to be updated. We could, but shouldn't use setState for this, as long it may alter the way Component work.
Ie - double, but in real triple, render. As long extra time, it will consume, is not comparable to the rebuild time - this is fine. PS: And thank you for a conversation, I've just understood that comparing this.version and "current" is the root cause of #923, as long current does not increment without babel plugin. |
@gaearon can this please be elevated from an "enhancement" to a "bug"? Current stable React is meant to be supported according to peer deps, yet here is the sort of console output we have to ignore: These false positives are a big confusion and obfuscate real warnings that are really helpful in this period of learning and transition to the new component API. This issue will affect the DX for a lot of people; Is there something blocking #927? |
@jaydenseric - nothing. Did not get a chance to properly test the changes. Should be ok, but I am not going to ship something, which could possibly break your stuff. |
Making RHL more React 16.3 compatible #918
I think the issue is that React uses a flag on the method to determine whether it's coming from If I change this method to include Object.assign(wrappedMethod, realMethod); before returning |
I'll update proxy code to keep everything from original class. @gaearon - should I also keep method arity, or (I hope) argument count does not count? |
Arity shouldn’t matter although preserving it is always nice if it’s not too difficult. |
This includes name, arity, toString and everything else possible stored among original method.
In review. |
This includes name, arity, toString and everything else possible stored among original method.
This includes name, arity, toString and everything else possible stored among original method.
fix: Proxy should keep methods own props. #918
Patch version released. v4.1.1 |
I'm working with React 16.3 and the HMR is broken in 4.1.0 and 4.1.1. |
Can you provide a repro case? |
You caught me unprepared, it might take me a lot of time. My project is not small, but it doesn't use anything special either. package.json "scripts": {
"start": "webpack-serve", .babelrc{
"presets": [
"@babel/preset-flow",
"@babel/preset-react",
["@babel/preset-env", { "modules": false }]
],
"plugins": [
"@babel/plugin-proposal-class-properties",
"@babel/plugin-proposal-object-rest-spread",
"@babel/plugin-syntax-dynamic-import"
],
"env": {
"test": {
"plugins": [
"@babel/plugin-transform-modules-commonjs"
]
},
"development": {
"plugins": [
"react-hot-loader/babel"
]
},
"production": {
"plugins": [
"@babel/plugin-transform-react-constant-elements",
"@babel/plugin-transform-react-inline-elements",
"babel-plugin-transform-react-pure-class-to-function",
"babel-plugin-transform-react-remove-prop-types"
]
}
}
} App.js...
let exportedApp = App;
if (__DEV__) {
const { hot } = require('react-hot-loader');
exportedApp = hot(module)(App);
}
export default connect(mapStateToProps)(exportedApp); index.jsimport React from 'react';
import { render } from 'react-dom';
import App from './components/App';
import { Provider } from './store'; // store made with the new Context API
const appElement = document.getElementById('root');
render(
<Provider>
<App />
</Provider>
, appElement); |
@elisherer - you can activate debug mode - https://github.com/gaearon/react-hot-loader#setconfigconfig - and it shall explain what is wrong. |
I've double checked and added a simple test to be confident about - everything is still 👌 |
@theKashey, Sorry, I don't get any debug info besides the regular logs: |
@elisherer - just to double check - App is included into The main difference between 4.0.1 and 4.1 - SFCs are no longer converted into Stateful components, and as result - they lose "brains". Your application worked because "safety net" worked. I've removed it from SFC, and it got broken. I'll be quite keen to get an example to play with. You can send it in private, if it is not public. Also, you can try to restore that net - just add That safety net actually activates "React-Hot-Loader" if it did not properly do it's work. As long there are no errors - look like RHL is just doing nothing, ignoring the update. |
Here's my two cents. I have followed the instruction and it is just working good with React 16.3. Foo.jsx import React from 'react';
import { hot } from 'react-hot-loader';
import PropTypes from 'prop-types';
class Foo extends React.PureComponent {
static propTypes = {
categories: PropTypes.arrayOf(PropTypes.number),
};
static defaultProps = {
categories: [],
};
state = {
foo: 'Bar',
};
render() {
return (
<div className="foo-container">{this.state.foo}</div>
);
}
}
export default hot(module)(Foo); The only difference is that I haven't made an export hot, while connecting it with the store. I am using Redux though and my App.jsx import React from 'react';
import { render } from 'react-dom';
import { Provider } from 'react-redux';
import Foo from './Foo';
import store from './store';
const Root = (
<Provider store={store}>
<Foo />
</Provider>
);
render(Root, document.getElementById('foo-app')); And to have hot reloading within the store, store.js import { createStore } from 'redux';
import rootReducers from './reducers/rootReducers';
// Create the store
const store = createStore(
rootReducers,
/* eslint-disable no-underscore-dangle */
// Add devtool in an isomorphic way
typeof window !== 'undefined' &&
window.__REDUX_DEVTOOLS_EXTENSION__ &&
window.__REDUX_DEVTOOLS_EXTENSION__()
/* eslint-enable */
);
// webpack hot middleware support
if (module.hot) {
module.hot.accept('./reducers/rootReducers', () => {
/* eslint-disable global-require */
const nextRootReducers = require('./reducers/rootReducers').default;
/* eslint-enable */
store.replaceReducer(nextRootReducers);
});
}
// export the store
export default store; And all these setup works with webpack dev middle and webpack hot middleware. Since I am developing a WP plugin, I couldn't use Webpack Dev server directly. So I used the middlewares inside browsersync (all connected with a simple gulp task). gulpfile.js const gulp = require('gulp');
const browserSync = require('browser-sync').create();
const webpack = require('webpack');
const webpackDevMiddleware = require('webpack-dev-middleware');
const webpackHotMiddleware = require('webpack-hot-middleware');
// Get the function for creating varying config
const webpackConfig = require('./config/webpack.config');
// Our local config
const localConfig = require('./config/local.config');
gulp.task('serve', () => {
const config = webpackConfig('development', localConfig);
const webpackBundler = webpack(config);
const devMiddleware = webpackDevMiddleware(webpackBundler, {
noInfo: true,
publicPath: config.output.publicPath,
stats: { colors: true },
});
const devHotMiddleWare = webpackHotMiddleware(webpackBundler);
browserSync.init({
logLevel: 'info',
port: localConfig.port,
ui: localConfig.ui,
debugInfo: true,
proxy: {
target: localConfig.proxy,
// Middleware for webpack hot reload
middleware: [
// converts browsersync into a webpack-dev-server
devMiddleware,
// hot reload JS
devHotMiddleWare,
],
},
host: localConfig.host,
open: false,
notify: localConfig.notify,
background: true,
});
// Full reload on php changes
gulp.watch(PATHS.php.src).on('change', browserSync.reload);
// JS & CSS will be handled by webpack on the go
}); The codes are stripped down so those are missing some imports. I hope the concepts and codes above helps @elisherer to debug your issue. I don't think it has anything to do with react-hot-loader rather how you have implemented it. Also, I guess you do have the |
@theKashey this is still open despite being listed as fixed in the 4.1.0 release notes. Is there a commit that fixed it? |
@swrobel it was "fixed" in 4.1.0, and yet again in "4.1.1" 4 days ago, and now I am waiting confirmation from @elisherer and @mvestergaard that this time everything is ok.
|
ill try to create a repro repo asap |
@theKashey my issue was resolved with 4.1.1, thank you. |
It has something to do with me using
All is working well besides the Maybe I should open another issue, since it doesn't relate to @mvestergaard's issue. |
@elisherer - this is not due to this issue, and it is easy to "fix" it - just remove "Prevent" component. This one is ✅🤘 |
Warning in development mode is likely from dev server: gaearon/react-hot-loader#918
Warning in development mode is likely from dev server: gaearon/react-hot-loader#918
Currently, we rely on
componentWillReceiveProps
to perform sync update and syncforceUpdate
. So - this method does not exist anymore.We have 2 options:
1 - rely on subrender, ie async updates. It is a dev mode, nobody cares about double rendering on rare hot updates. Thus remove AppContainer completely. This will also solve
2 - find another way. But I don't see any.
The text was updated successfully, but these errors were encountered: