What does 'Only a ReactOwner can have refs.' mean? - reactjs

I have a simple react component with a form in it:
var AddAppts = React.createClass({
handleClick: function() {
var title = this.refs.title.getDOMNode().value;
....
var appt = {
heading: title
...
}
CalendarActions.addAppointment(appt);
},
render: function() {
return (
<div>
<label>Description</label>
<input ref="title"></input>
...
</div>
);
}
});
module.exports = AddAppts;
I am trying to render this component in another react component:
var AddAppt = require('./AddAppts');
render: function() {
return (
<div>
<AddAppt />
</div>
);
}
but I get this error:
Uncaught Error: Invariant Violation: addComponentAsRefTo(...): Only a ReactOwner can have refs. This usually means that you're trying to add a ref to a component that doesn't have an owner (that is, was not created inside of another component's `render` method). Try rendering this component inside of a new top-level component which will hold the ref.
I have googled it, but cannot figure out what I need to do to fix this issue.

This is FYI for people using react and redux-devtools who are getting OP's message. Your structure looks like
project
client
node_modules
react
redux-devtools
node_modules
react
The code in client will require the first react module; that in redux-devtools will require the other react. The react module keeps state and assumes it has all the state.
You get the OP's message because your state is split between the 2 react modules. This situation is what I believe #asbjornenge refers to.
I was bundling the client code with webpack, so I used that to handle the issue. You can force all require and import to always use the first react by adding the following to webpack.config.js
module.exports = {
...
resolve: {
alias: {
'react': path.join(__dirname, 'node_modules', 'react')
},
extensions: ['', '.js']
},
...
);
I have not looked into what I would need to do if the situation occurred with unbundled code running on node.

I encountered this error when a component module I was using had it's own react dependency installed. So I was using multiple versions of React.
Make sure NOT to list react under dependencies in your package.json.
This is why we have peerDependencies ;-)

Just in case. Be aware of the React module name you are using (it is case-sensitive). I've got the same error when by coincidence I tried to require React dependency with different names in two separate modules.
//module1.js
var React = require('react');
...
//module2.js
var React = require('React');
....
It works and even renders something but the Only a ReactOwner can have refs... error appears.

Rearranging the script resolved the issue.
Wrong.
<script src="./lib/react.js"></script>
<script src="./lib/react-dom.js"></script>
<script src="./lib/react-with-addons.js"></script>
Correct
<script src="./lib/react.js"></script>
<script src="./lib/react-with-addons.js"></script>
<script src="./lib/react-dom.js"></script>
Reference https://github.com/gcanti/tcomb-form/issues/107#issuecomment-150891680

I saw this error while developing a react module that was linked to a test project using npm link. Switching to a regular dependency solved the problem.
It seems that React doesn't like npm link.

There is another situation.
I set the React as external library in the webpack.config.js and import react.js from cdnjs.
externals: {
'react': 'React'
}
When I using an ui library depend on React,such as material-ui,react-bootstrap,this issue occurred.

am writing with my old pen. make sure in your project root package.json move react dependency as early as possible. still you are getting issue? & if you are using npm modules and grunt task, you can add below clean task to remove inner components react(duplicates).
clean: {
react : ['node_modules/**/react','!node_modules/react']
},

I saw this error after I moved my package.json file up a level, so I had 2 node_modules directories in my project (one in ./node_modules and another in ./web/node_modules). Removing the old directory fixed the problem.

For me the reason for the same problem was that I've imported the ReactDom globally, as a property of the window object, like this:
import ReactDOM from 'react-dom'
window.ReactDOM = ReactDOM
removing window.ReactDOM = ReactDOM fixed the problem.

Similar to this answer, I was seeing this error while using a separate module that I had been developing in a separate directory using yarn link.
The solution was to run yarn unlink module-name in my project's working directory. I then removed node_modules and ran yarn upgrade module-name and yarn for good measure.

Instead of
<input ref="title"></input>
Try this
<input ref={(title) => this.title = title}></input>

None of the given solutions worked for me, though they certainly helped show me where to look.
For some reason my project has two node_modules folders - one in the root directory and one a level up. I'm new to React so I don't know if this is normal or what. I'm just going with what Visual Studio gave me when I started a new project.
Anyway, I knew which module was causing the problem, and it happened to only exist in one of the node_modules folders.
I moved the problem module over to the other node_modules folder. Problem solved.

Related

Material UI withStyles in an NPM package causes errors when used through npm link

I'm trying to locally build the oodt_fm_plugin NPM package and link it locally to the oodt_opsui_sample_app. However, when I'm trying to do that, the following error is thrown in the browser.
Error: Minified React error #321; visit
https://reactjs.org/docs/error-decoder.html?invariant=321 for the full
message or use the non-minified dev environment for full errors and
additional helpful warnings.
The error goes away if I remove the withStyles HOC from the components in oodt_fm_plugin, but I want to preserve it for the material UI styles.
React components in the oodt_fm_plugin have been exported as follows. ( This plugin can be viewed at https://github.com/apache/oodt/tree/development/react-components/oodt_fm_plugin. )
export default withStyles(styles)(Product);
What I tried to overcome this are as follows, but none of those solved the issue.
Making react and react-dom packages in the plugin, dev dependencies
Adding the following snippet to the webpack.config.js of the plugin.
resolve: {
modules: [path.resolve('node_modules'), 'node_modules'],
},
Can someone point me in the right direction so that I can set up both oodt_fm_plugin and oodt_ui_sample_app correctly in local dev environment? Helpful advice is highly appreciated.
Well, I finally managed to solve the problem, after trying for several days. As I found out, it was not a problem with material ui, but with the Create React App. This Github issue comment helped me to solve my problem.
For extra clarity, I will quote the issue comment in this answer itself, so that it will remain here even if the comment gets deleted.
^ Ok, the solution I went for to solve this for create-react-app is to
use react-app-rewired and customize-cra.
Here is my config-overrides.js :
const {
override,
addWebpackAlias, } = require("customize-cra");
const path = require('path');
module.exports = override(
addWebpackAlias({
react: path.resolve('./node_modules/react')
}) )
Example project: https://github.com/dwjohnston/material-ui-hooks-issue/tree/master
Then, modify the start script as follows.
"start": "react-app-rewired start"

requestAnimationFrame is not defined it Next.js with React Native Web (Animated module)

I'm working on Next.js and React-Native-Web. I managed to run them together following the official Next.js example but when I'm trying to use the Animated package from the react-native it fails with Error that the requestAnimationFrame isn't defined. Basically this functionality does the node_modules package but I set the alias in webpack to translate all react-native requires to the react-native-web so even the node_modules package should use the react-native-web.
Any suggestions on how to solve it?
ReferenceError: requestAnimationFrame is not defined
at start (...node_modules\react-native-web\
dist\cjs\vendor\react-native\Animated\animations\TimingAnimation.js:104:11)
enter code here
Thanks for any help!
The problem is in the missed RequestAnimationFrame functionality at the server. This error happens when Next.js tries to render the component during SSR.
Unfortunately, there is no polyfill, etc. for such purpose so I just decided to use the Next.js dynamic imports for a Component that has animation functionality.
Next.js Official documentation
My own case оust to show how code looks:
import dynamic from 'next/dynamic';
const AutocompleteDropdown = dynamic(
() => import(
'myAwesomeLib/components/dropdown/autocomplete/AutocompleteDropdown'
),
{
ssr: false,
}
);
Now you can use the AutocompleteDropdown as the standard JSX component
I'm coding an App with React Native Web and NextJS 12, and in 2021 I encounter this problem and I fixed it, but now I know my fix was only for Next Dev, because it returned for Next Production Build.
Solution details:
No Dynamic import (which is useful too, but can be annoying when having lot of components using it)
Using RAF polyfill and Webpack ProvidePlugin.
Main thing to have in mind is that next.config.js with webpack 5 is going to check the codes first before even reach next entry points _documents.js and _app.js. It means that, you can put polyfill in those entry point files, it will still raise error of RAF undefined. You have to make requestAnimationFrame ready for config check.
DEV approach that will work on Next DEV only. Install RAF package https://www.npmjs.com/package/raf and In next.config.js add codes:
const raf = require('raf');
raf.polyfill();
This will add requestAnimationFrame and cancelAnimationFrame function to global and window object if they don't have it. In our case, it would add it in global for NodeJS.
But this solution won't work when executing npm run dev. I don't know why, if anyone knows why Next or Webpack 5 act differently from DEV to PRODUCTION, let me know.
Complete Solution:
Use ProvidePlugin config of webpack 5 https://webpack.js.org/plugins/provide-plugin/ . Create a file to use as modules, let's say: raf.js in root project or anywhere you want:
const raf = require('raf');
const polys = {};
raf.polyfill(polys);
module.exports = polys.requestAnimationFrame;
And in next.config.js use it inside webpack: () = {} like:
webpack: (config, options) => {
// console.log('fallback', config.resolve.fallback);
if (options.isServer) {
// provide plugin
config.plugins.push(
new options.webpack.ProvidePlugin({
requestAnimationFrame: path.resolve(__dirname, './raf.js'),
}),
);
}
And now, it's up to you to adapt to your existing config logic. By doing this, in Production Build, NextJS is injecting the requestAnimationFrame function in Server Side everywhere a module is using it.

create-react-library not working with styled components

I'm using create-react-library to build my component library, and I've attempted to use Styled Components, but I keep getting a React hooks error.
Here's my code: https://github.com/emmabostian/component-library
And here's the error:
Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
I am not using React hooks anywhere, my React and React DOM versions match and I do not have multiple versions of React.
Check your package.json file you appear to have dependencies react / react-dom version 16 but peer dependencies for versions 15 . I think this is the cause of your problem , remove the peer dependencies. Also you don't need to write your components as class based if all you are doing is rendering use a functional component approach instead.
The dependencies in the included example project are very outdated.
Instead I set up a new separate example project, which perfectly renders your button:
npx create-react-app component-library-example
cd component-library-example
npm install --save emmas-super-cool-component-library
npm start
App.js:
import React from "react";
import { PrimaryButton } from "emmas-super-cool-component-library";
const App = () => (
<PrimaryButton
onClickHandler={() => {
alert("clicked");
}}
>
text
</PrimaryButton>
);
export default App;
Result:
I've recently used create-react-library, and had encountered the same issue. The error message exactly makes sense in this case. The issue will not happen when you actually publish the package and consume it at a consumer application. This means, the problem is with your example folder. If you look at package.json, that's inside example folder, you can see there are library references for react, react-scripts, react-dom etc. Referring those with file protocol like below will solve your problem.
"dependencies": {
"library-name": "file:..",
"react": "file:../node_modules/react",
"react-dom": "file:../node_modules/react-dom",
"react-scripts": "file:../node_modules/react-scripts"
"node-sass": "file:../node_modules/node-sass"
},
Clear your node_modules as well as package-lock.json before trying this.

How to re-use a React library with hooks

I'm writing my own library to help building forms with React.
The goal is to be able to re-use it in any React application (made from scratch, with create-react-app, nextjs, other ?)
My problem is that I can't firgure out how to re-use it.
Here is the first issue I encountered when I tried to reuse my library in another project :
Invalid Hook Call Warning
React says that the reason could be one of the following :
You might have mismatching versions of React and React DOM.
You might be breaking the Rules of Hooks.
You might have more than one copy of React in the same app.
After investigation, I've excluded points 1. and 2.
I was using Parcel in the first place to build my library but I needed to exclude React from the bundle to solve 3.
That's why I switched to Webpack and moved the React dependency to the peerDependencies + devDependencies.
I've tried different webpack configurations :
const config: webpack.Configuration = {
...
externals: {
react: 'React'
}
}
--> which leads to the following error in the consuming application :
React is not defined
const config: webpack.Configuration = {
...
externals: {
react: {
root: 'React',
amd: 'react',
commonjs: 'react',
commonjs2: 'react',
umd: 'react',
}
}
}
--> which leads to the following error :
Cannot read property 'createContext' of undefined
I've tried to use my library with npm link and also by publishing it on npm but the result is the same.
Step to reproduce :
Install #mlaopane/formhook in your react application (npm i #mlaopane/formhook or yarn add #mlaopane/formhook)
Try to use a component, for example
import { Form } from '#mlaopane/formhook'
export default function App() {
return <Form />
}
You should see the error in the console
Thank you for helping me with this :)
NB: This is my first issue, please tell if more information is needed.
I've finally found a solution, inspired by create-react-library.
It looks like Rollup is a better candidate for bundling React libraries.
Even if I still can't link my library locally, it can be used when published.

Multiple copies of React in my Application

I am using react-treelist component and inside that i am using office-ui-fabric callout(its like a tooltip) component to have a tooltip on elements in tree structure when i am running this program it runs correctly but when i am bundling and using the bundle file in my project as a module it gives error:-
Exception in Layer.componentDidUpdate(): Invariant Violation: addComponentAsRefTo(...): Only a ReactOwner can have refs. You might be adding a ref to a component that was not created inside a component's render method, or you have multiple copies of React loaded
I have tried many solutions from diff forum but none of them worked.I am sure problem is of multiple copies of react.
Details of what i did
I cloned react-treelist from github then i installed office-ui-fabric module then i changed some code to make callout component work with react-treelist, i did npm start it worked fine the i did npm run dist and copied the bundle file to my project directory inside a folder named react-treelist and then imported that file as module in my code and ran the code it gave me the above error.
Can anybody suggest me how to accomplish the above task without having multiple copies of react in my application
If you use webpack to build your application, you can use the resolve.alias configuration option to make sure that all modules refer to the same react library:
resolve: {
alias: {
'react': fs.realpathSync('node_modules/react'),
'react-dom': fs.realpathSync('node_modules/react-dom')
}
}
If you use web pack then you can fix it by adding the following to Webpack config
externals: {
'react': 'React',
'react-dom': 'ReactDOM'
}

Resources