React passing context Cannot read properties of undefined (reading 'map') - reactjs

I'm trying to follow a TodoList tutorial but I'm already bumbing into this js mapping error.
It's about passing a context from a "TodoContextProvider" into the child components "TodoTable".
The error message I get is the following:
TodoTable.js:8 Uncaught TypeError: Cannot read properties of undefined (reading 'map')
At this point (with these 3 files), the "Do something" task should appear in the dom, but instead I'm getting the error above.
I have checked the code several times but can't find the error.
Since I'm stuck for several hours now, I'd be happy if someone could have an eye on it, thanks:
// Entry point App.js root/assets/js/App.js
import React from "react";
import { createRoot } from "react-dom/client";
import TodoTable from "./components/TodoTable";
import TodoContextProvider from "./contexts/TodoContext";
export default class App extends React.Component {
render() {
return (
<TodoContextProvider>
<TodoTable />
</TodoContextProvider>
);
}
}
const container = document.getElementById("root");
const root = createRoot(container);
root.render(<App />);
// TodoContext.js root/assets/js/contexts/TodoContext.js
import React, { createContext } from "react";
export const TodoContext = createContext();
class TodoContextProvider extends React.Component {
constructor(props) {
super(props);
this.state = {
todos: [{ task: "Do something" }],
};
}
// Create
createTodo() {}
// Read
readTodo() {}
// Update
updateTodo() {}
// Delete
deleteTodo() {}
render() {
return (
<TodoContext.Provider
value="{{
...this.state,
createTodo: this.createTodo.bind(this),
updateTodo: this.updateTodo.bind(this),
deleteTodo: this.deleteTodo.bind(this),
}}"
>
{this.props.children}
</TodoContext.Provider>
);
}
}
export default TodoContextProvider;
// TodoTable.js root/assets/js/components/TodoTable.js
import React, { useContext } from "react";
import { TodoContext } from "../contexts/TodoContext";
function TodoTable() {
const context = useContext(TodoContext);
return (
<div>
{context.todos.map((todo) => (
<div>{todo.task}</div>
))}
</div>
);
}
export default TodoTable;

Related

ReactJS: Problem accessing this.context in a class based consumer component

I have a problem to access this.context in a class based consumer component. I have the following situation:
AppContext.js:
import React from "react";
const ContactContext = React.createContext(); // Create our context
export default ContactContext;
DataProvider.js:
import React, { Fragment } from "react";
import AppContext from "./AppContext";
export default class DataProvider extends React.Component {
state = {
contacts: {
contact1: {
id: 1,
firstName: 'Test User FN',
lastName: 'Test User LN'
}
}
};
render() {
return (
<>
<AppContext.Provider value={{contacts: this.state.contacts}}>
{this.props.children}
</AppContext.Provider>
</>
);
}
}
App.js:
import React from 'react';
import DataProvider from "./DataProvider";
import Contact from './components/contact/contact.component';
export default class App extends React.Component {
render() {
return (
<div>
<div className="container">
<DataProvider>
<Contact contactIndex={0}/>
</DataProvider>
</div>
</div>
);
}
}
The consumer Contact.js:
import React, { Component } from "react";
import AppContext from '../context/AppContext'
export default class Contact extends Component {
static contextType = AppContext;
componentDidMount () {
console.log('My context is: ' + this.context);
}
render() {
return (
<div className="card"></div>
);
}
}
The console output is:
My context is: undefined
Thanks for any help
Regards
Dakir
Only difference I see in the other answer's CodeSandbox is the import path is different.
import AppContext from "./AppContext";
vs:
import AppContext from '../context/AppContext'
Maybe OP has a filepath/import error?
p.s. If this is the error, TypeScript is a lifesaver for avoiding these kind of things in JS.
Your code seems right to me, I tried to replicate it in a Sandbox to find out the error and somehow works like a charm.
https://codesandbox.io/s/interesting-https-emgoz?file=/src/App.js
Tried to spot the difference but I couldn't honestly.

React context is undefined

This is my first time using Reactjs with Laravel. I'm trying to send data among components but the context returns as undefined. I want to send data from Product_Detail.js to Cart.js
globalContext.js
import React from "react";
export const MContext = React.createContext(); //exporting context object
export class MyProvider extends React.Component {
constructor() {
this.state = {
message: ""
};
}
render() {
return (
<MContext.Provider value={{ message: "kkk" }}>
<Cart />
<Product_Detail />
{this.props.children} //this indicates that all the child tags with
MyProvider as Parent can access the global store.
</MContext.Provider>
);
}
}
export const MyConsumer = MContext.Consumer;
Cart.js
import { MyConsumer } from "./globalContext";
<MyConsumer>{context => <p>{console.log("CCC", context)}</p>}</MyConsumer>;
export default Cart;
if (document.getElementById("shoppingCart")) {
ReactDOM.render(<Cart />, document.getElementById("shoppingCart"));
}
Product_Detail.js
import { MyConsumer } from "./globalContext";
<MyConsumer>
{context => (
<button
className="flex-c-m sizefull bg1 bo-rad-23 hov1 s-text1 trans-0-4"
onClick={() => {
console.log("kkkk", context);
}}
>
Add to Cart
</button>
)}
</MyConsumer>;
export default Product_Detail;
if (document.getElementById("product_detail")) {
ReactDOM.render(
<Product_Detail />,
document.getElementById("product_detail")
);
}
App.js
import Cart from "./components/Website/Cart";
import Product_Detail from "./components/Website/Product_Detail";
import { MyProvider } from "./components/Website/globalContext";
It's not entirely clear what you're rendering inside your app component, but I think what is going wrong is that your components are not correctly wrapped by your Provider.
Your App component should look something like this:
import React from "react";
import Cart from "./components/Website/Cart";
import Product_Detail from "./components/Website/Product_Detail";
import { MyProvider } from "./components/Website/globalContext";
const App = () => {
return (
<MyProvider>
<Cart />
<Product_Detail />
</MyProvider>
);
};
export default App;
And your globalContext like this:
import React from "react";
export const MContext = React.createContext(); //exporting context object
export class MyProvider extends React.Component {
constructor(props) {
super(props);
this.state = {
message: ""
};
}
render() {
return (
<MContext.Provider value={{ message: "kkk" }}>
{this.props.children}
</MContext.Provider>
);
}
}
export const MyConsumer = MContext.Consumer;
This way the value you passed to your provider get's logged out when Cart is rendered and when you click on the button rendered by Product_Detail.
Also I'm assuming that you're importing React inside the Cart and Product_Detail components and that you're correctly defining these components.

Text not being retrieved from component in this React application

I'm new to react so I can't seem to figure out what I'm doing wrong here. The 'Good Morning Student' greeting isn't being displayed. The error message claims that 't is not defined' but I thought that's what I'm doing in the const.
I'm assuming its something wrong with the syntax but from what I've been reading this is all I can think of it to be.
index.js file
module.exports = {
homepage: {
'greeting': 'Good Morning Student',
}
};
greeting.js file
import PropTypes from 'prop-types';
import React from 'react';
class Greeting extends React.Component {
render() {
const {
p: { t }
} = this.props;
return (
<p> {t('greeting')} </p>
);
}
}
Greeting.PropTypes = {
Greeting: PropTypes.string.isRequired
};
export default Greeting;
homepage.js
<Greeting />
You need to pass prop p to your <Greeting /> component. See this:
const obj = { t: {'greeting': 'Good Morning Student'}}
<Greeting p={t} />
then you can access it from props:
const {
p: { t }
} = this.props;
You have not passed in a t function to your Greeting component, that's why it claims to be undefined. In the below code I have imported the data from index.js and passed it into the Greeting component as the greeting prop. Then inside the Greeting component itself I destructure greeting out of the props to use it.
Note that the path to the index file is a guess so edit this to make sure it is pointing to the actual place the file lives in the directory.
hompage.js
import data from 'index';
...
<Greeting greeting={data.plp.greeting} />
greeting.js
import PropTypes from 'prop-types';
import React from 'react';
class Greeting extends React.Component {
render() {
const {
greeting
} = this.props;
return (
<p>{greeting}</p>
);
}
}
Greeting.PropTypes = {
greeting: PropTypes.string.isRequired
};
export default Greeting;

React categories.map is not a function

I want to render an array to react console, but I get the following error :
TypeError: products.map is not a function
This is my App.js:
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
class App extends Component {
state = {
categories: []
}
renderCategory = ({category_id, name}) => <div key={category_id}>{name}</div>
render() {
const categories = this.state;
return (
<div>
{categories.map(this.renderCategory)}
</div>
);
}
}
export default App;
After i run : npm start in console I got no errors in compilation !
Destructuring is incorrect. Update to :
const { categories } = this.state;

Embedded Child Component in React is Undefined

I have the following parent component:
import React, { Component, PropTypes } from 'react'
import { connect } from 'react-redux';
import {bindActionCreators} from 'redux';
import _ from "lodash";
import ChildComponent from "./ChildComponent";
class ParentComponent extends Component {
constructor(props) {
super(props);
this.state = {
};
}
render() {
return (
<div>
I'm at Parent
<ChildComponent/>
</div>
);
}
}
function mapStateToProps(state) {
return { }
}
export default connect(mapStateToProps, null)(ParentComponent);
Inside the parent has a component called ChildComponent that looks like this:
import React, { Component, PropTypes } from "react";
import { connect } from "react-redux";
import { reduxForm } from "redux-form";
import { bindActionCreators } from "redux";
class ChildComponent extends Component {
constructor(props) {
super(props);
}
componentWillMount() {
}
render() {
return (
<div>
at the child
</div>
);
}
}
function mapDispatchToProps(dispatch) {
return bindActionCreators(
{
},
dispatch
);
}
function mapStateToProps(state) {
return {
};
}
export default connect(mapStateToProps, mapDispatchToProps)(
ChildComponent
);
When I try adding the child component I keep getting this error:
But if I click continue the page turns back to normal. I don't understand how the child component is undefined. It's just embedded and does not include any props.
UPDATE:
I'm not getting the error anymore but I notice my page turns blank when I open this particular component. I'll be doing a bit more troubleshooting.
I tried out your code, and it works fine for me. My thought was maybe what your entry file looks like? or file structure? If you like you can try the following syntax for the parent and child - it worked this way as well:
Child:
const mapStateToProps = () => {
return {}
}
const ConnectedChildComponent = connect(
mapStateToProps,
{})(ChildComponent)
export default ConnectedChildComponent;
Parent:
const mapStateToProps = () => {
return {}
}
const ConnectedParentComponent = connect(
mapStateToProps,
{})(ParentComponent)
export default ConnectedParentComponent;
In your ParentComponent change:
import ChildComponent from "./ChildComponent";
to
import ChildComponent from "./ChildComponent.jsx";
i.e. add the missing ".jsx" extension. Your code is most likely determining the import to be a ".js" file by default, whereas it's actually a ".jsx" file.

Resources