I'm new in react-redux and I'm trying to build a todo app with a reference but I keep getting this 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:
- You might have mismatching versions of React and the renderer (such as React DOM)
- You might be breaking the Rules of Hooks
- You might have more than one copy of React in the same app
and here is the error code:
4 | import App from "./App";
5 | import reportWebVitals from "./reportWebVitals";
6 |
> 7 | ReactDOM.render(
8 | <React.StrictMode>
9 | <App />
10 | </React.StrictMode>,
I can't understand how there is an error?
here are some of my files:
App.js
import React from 'react';
import './App.css';
import AddTodo from './components/addTodo'
import TodoList from './components/todoList'
import VisibilityFilter from './components/visibilityFilter'
import {Provider} from 'react-redux'
import store from './redux/store'
function App() {
return (
<Provider store={store}>
<div className="App">
<h1>TODO Managers</h1>
<AddTodo/>
<TodoList/>
<VisibilityFilter/>
</div>
</Provider>
);
}
export default App;
index.js
import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById("root")
);
reportWebVitals();
addTodo.js
import React, { useState } from "react";
import { connect } from "react-redux";
import { addTodo } from "../redux/actions";
function AddTodo({ addTodo }) {
const [input, setInput] = useState("");
const inputHandler = (e) => {
setInput(e.target.input);
};
const addHandler = () => {
setInput("");
addTodo(input);
};
return (
<>
<input
type="text"
onChange={inputHandler}
input={input}
placeholder="You text here"
/>
<button onClick={addHandler}>Add</button>
</>
);
}
export default connect(null, { addTodo })(AddTodo);
todoList.js
import React from 'react'
import { connect } from 'react-redux'
import * as _ from 'underscore'
import { FILTER_ALL, FILTER_COMPLETED } from '../redux/actionTypes'
import { toggleTodo } from '../redux/actions'
const Todo = ({ todo, id, toggleTodo }) => (
<li className={todo.completed ? 'completed' : ''} onClick={() => toggleTodo(id)}>{todo.text}</li>
)
function TodoList({ todos, toggleTodo }) {
return (
_.keys(todos).map((id) => (
<Todo key={id} id={id} toggleTodo={toggleTodo} todo={todos[id]} />
))
)
}
const mapState = (state) => {
if (state.visibilityFilter.activeFilter === FILTER_ALL) {
return { todos: state.todos.data }
} else if (state.visibilityFilter.activeFilter === FILTER_COMPLETED) {
return ({
todos: _.pick(state.todos.data, (todo) => todo.completed)
})
} else {
return ({
todos: _.pick(state.todos.data, (todo) => !todo.completed)
})
}
}
export default connect(mapState, { toggleTodo })(TodoList);
visibilityFilter.js
import React from 'react'
import { connect } from 'react-redux'
import { setFilter } from '../redux/actions'
import { Filters } from '../redux/actionTypes'
function VisibilityFilter({ activeFilter, setFilter }) {
return (
Filters.map((filter, i) => (
<button
className={filter === activeFilter ? 'active' : ''}
onClick={() => setFilter(filter)}
key={`filter-${i}`}>
{filter}
</button>
))
)
}
const mapState = (state) => ({ activeFilter: state.visibilityFilter.activeFilter })
export default connect(mapState, { setFilter })(VisibilityFilter)
package.json
{
"name": "todo",
"version": "0.1.0",
"private": true,
"dependencies": {
"@testing-library/jest-dom": "^5.14.1",
"@testing-library/react": "^11.2.7",
"@testing-library/user-event": "^12.8.3",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-scripts": "4.0.3",
"underscore": "^1.13.1",
"web-vitals": "^1.1.2"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}