When I first tried wiring up Firebase in a small react js app, I ran head-first into this error:
Uncaught TypeError: Cannot set property 'ReactFireMixin' of undefined
At first glance, it looked like I had messed up my imports or broken something in my build. After some digging, I realized the issue wasn’t just my code it was also about how ReactFireMixin works (or doesn’t work) in modern react js setups. Let me walk you through the problem, the fix, and then I’ll share a simple Firebase-backed todo app that helped me practice.
My First Attempt
Here’s the first version I wrote:
import react from 'react';
import {render} from 'react-dom';
import reactfire from 'reactfire';
import firebase from 'firebase';
class app extends react.component {
render() {
return <h1>
hello bitches!
</h1>
}
}
var element = react.createelement(app, {});
render(element, document.queryselector('.app'));
And here’s my webpack config at that time:
module.exports = {
entry: "./app/components/Main.js",
output: { filename: "public/bundle.js" },
module: {
loaders: [
{
test: /\.jsx?$/,
exclude: /(node_modules | bower_components)/,
loader: 'babel',
query: { presets: ['react', 'es2015'] }
}
]
}
}
Why the Error Happen
The ReactFireMixin
error shows up because the version of reactfire
I was pulling in expected React.addons
to exist. But in modern React, there’s no addons property anymore. Mixins were used with the old React.createClass
, and I was trying to use ES6 classes (class App extends React.Component
). These two approaches don’t play together.
So, the reasons boiled down to:
- The
reactfire
library was outdated for my setup. - Mixins aren’t supported in ES6 class components.
- I also had multiple casing typos:
react
→React
react.component
→React.Component
app
should beApp
(class names must be capitalized).react.createelement
→React.createElement
.document.queryselector
→document.querySelector
.
In short: the modern way to do this is to ditch ReactFireMixin completely and talk directly to the Firebase SDK (or use the new reactfire
hooks API).
The Fix Minimal Version
Here’s my working minimal version no mixins, just React and the Firebase SDK:
// src/index.jsx
import React from "react";
import { createRoot } from "react-dom/client";
// Firebase v9+ modular SDK
import { initializeApp } from "firebase/app";
import { getDatabase, ref, onValue } from "firebase/database";
// Firebase setup (use your own config values)
const firebaseConfig = {
apiKey: "YOUR_KEY",
authDomain: "YOUR_APP.firebaseapp.com",
databaseURL: "https://YOUR_APP.firebaseio.com",
projectId: "YOUR_APP",
storageBucket: "YOUR_APP.appspot.com",
messagingSenderId: "1234567890",
appId: "1:1234567890:web:abcdef",
};
const app = initializeApp(firebaseConfig);
const db = getDatabase(app);
class App extends React.Component {
state = { greeting: "hello there!" };
componentDidMount() {
const greetingRef = ref(db, "demo/greeting");
onValue(greetingRef, (snap) => {
const value = snap.val();
if (typeof value === "string") this.setState({ greeting: value });
});
}
render() {
return <h1>{this.state.greeting}</h1>;
}
}
const root = createRoot(document.querySelector(".app"));
root.render(<App />);
Updated Webpack Config
module.exports = {
entry: "./src/index.jsx",
output: { filename: "public/bundle.js" },
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: "babel-loader",
options: {
presets: ["@babel/preset-env", "@babel/preset-react"]
}
}
}
]
},
resolve: { extensions: [".js", ".jsx"] }
};
If I Really Want ReactFire
The modern reactfire
library doesn’t use mixins either. It uses providers and hooks:
import React from "react";
import { createRoot } from "react-dom/client";
import { FirebaseAppProvider } from "reactfire";
import { initializeApp } from "firebase/app";
const firebaseConfig = {/* ... */};
function App() {
return <h1>Hi from ReactFire hooks</h1>;
}
const root = createRoot(document.querySelector(".app"));
root.render(
<FirebaseAppProvider firebaseApp={initializeApp(firebaseConfig)}>
<App />
</FirebaseAppProvider>
);
With that, I can use hooks like useDatabase
, useDatabaseObjectData
, etc. No ReactFireMixin
needed.
Practice Feature Firebase Todo App
To cement what I learned, I built a tiny todo list that reads/writes to Firebase:
import React from "react";
import { createRoot } from "react-dom/client";
import { initializeApp } from "firebase/app";
import { getDatabase, ref, onValue, push, set, update } from "firebase/database";
const firebaseConfig = {
apiKey: "YOUR_KEY",
authDomain: "YOUR_APP.firebaseapp.com",
databaseURL: "https://YOUR_APP.firebaseio.com",
projectId: "YOUR_APP",
storageBucket: "YOUR_APP.appspot.com",
messagingSenderId: "1234567890",
appId: "1:1234567890:web:abcdef",
};
const fbApp = initializeApp(firebaseConfig);
const db = getDatabase(fbApp);
class App extends React.Component {
state = { todos: {}, input: "" };
componentDidMount() {
const todosRef = ref(db, "demo/todos");
onValue(todosRef, (snap) => {
this.setState({ todos: snap.val() || {} });
});
}
addTodo = async (e) => {
e.preventDefault();
const text = this.state.input.trim();
if (!text) return;
const listRef = ref(db, "demo/todos");
const newRef = push(listRef);
await set(newRef, { text, done: false, createdAt: Date.now() });
this.setState({ input: "" });
};
toggleTodo = (id, done) => {
const tRef = ref(db, `demo/todos/${id}`);
update(tRef, { done: !done });
};
render() {
const entries = Object.entries(this.state.todos);
return (
<div style={{ fontFamily: "sans-serif", maxWidth: 420, margin: "40px auto" }}>
<h1>Firebase Todos</h1>
<form onSubmit={this.addTodo} style={{ display: "flex", gap: 8 }}>
<input
value={this.state.input}
onChange={(e) => this.setState({ input: e.target.value })}
placeholder="Add a todo"
style={{ flex: 1, padding: 8 }}
/>
<button type="submit">Add</button>
</form>
<ul style={{ padding: 0, listStyle: "none", marginTop: 16 }}>
{entries.length === 0 && <li>No todos yet.</li>}
{entries.map(([id, t]) => (
<li
key={id}
style={{
display: "flex",
alignItems: "center",
gap: 8,
padding: "8px 0",
borderBottom: "1px solid #eee"
}}
>
<input
type="checkbox"
checked={!!t.done}
onChange={() => this.toggleTodo(id, t.done)}
/>
<span style={{ textDecoration: t.done ? "line-through" : "none" }}>
{t.text}
</span>
</li>
))}
</ul>
</div>
);
}
}
const root = createRoot(document.querySelector(".app"));
root.render(<App />);
Now I can add todos, toggle them, and see live updates straight from Firebase.
Final Thought
When I saw the ReactFireMixin
error, my first instinct was that I mis-configured webpack or react js. The real lesson, though, was that ReactFireMixin is simply not meant for modern React. By switching to the Firebase SDK (or the updated reactfire
with hooks), everything became cleaner, future proof, and easier to understand. If you hit this error, don’t waste time fighting with ReactFireMixin
. Instead, embrace the new patterns. And if you really want to practice, try building something small like the todo app above. It’s the fastest way to learn.