I have a table in my database cold Apoet in my table field could name so I try to bring the name from the database but when I run the app this message appear
undefined is not an object (evaluating abc.name)
below my code
import React from 'react';
import {useEffect} from 'react';
import {useState} from 'react';
import { useRoute } from '#react-navigation/native';
import { DataStore } from 'aws-amplify';
import { Apoet } from '../../models';
const ProductScreen = () => {
const route = useRoute();
console.log(route);
const {abc, setABC}= useState<Apoet | undefined>(undefined);
useEffect (()=>{
if(!route.params?.id){
return ;
}
DataStore.query(Apoet,route.params.id).then(setABC)
},[route.params?.id]);
return (
<View>
<Text>{abc.name} </Text>
</View>
)}
Your useState is wrong, change with square brackets. Also be sure route changes as you expect otherwise it will be undefined again since your initial state value is also undefined
const [abc, setABC] = useState<Apoet | undefined>(undefined);
Issues
You've incorrectly accessed the return value from the useState hook, it returns an array, not an object.
const {abc, setABC} = useState<Apoet | undefined>(undefined);
You also use an undefined initial value, so attempting to access into it will throw an error.
Solution
Fix the return and use array destructuring assignment and use a valid initial value.
const [abc, setABC] = useState<Apoet>({});
...
<Text>{abc.name}</Text>
abc is now defined and can access a name property that will be undefined util the state is updated.
Or if you want to keep it allowed to be undefined, use a null check or Optional Chaining operator on the name property access.
Example:
const [abc, setABC] = useState<Apoet | undefined>();
...
<Text>{abc && abc.name}</Text>
or
<Text>{abc?.name}</Text>
Related
I am trying to make a dark/light theme system in my project, but I am having some problems with the code.
This line of code works fine in javascript:
const [darktheme, setDarkTheme] = useContext(ThemeContext);
But when I write it into typescript, I get 6 errors.
I know that some of these variables need to have their type declared, but I only know the type of the darkTheme variable, which is a boolean.
After I declare the types, 2 errors go away, but there is still 4 errors!
const [darktheme: boolean, setDarkTheme: any] = useContext(ThemeContext);
I used any after dark theme, which is not good practice but I didn't know the type
Now I just get these errors:
I think that the main problem with my project is that I am trying to integrate javascript with typescript. I don't know if that is normal or not, but I am doing it because some components are much easier to write with typescript, and some more basic components are better written in javascript.
Here is part of my app.js:
// Context
export const ThemeContext = React.createContext();
function App() {
const [darkTheme, setDarkTheme] = useState(false);
return (
<ThemeContext.Provider value={[darkTheme, setDarkTheme]}>
,and when I use the function in this component, it works just fine:
import React, { useContext } from 'react';
import { ThemeContext } from '../App';
import Button from 'react-bootstrap/Button';
export default function DarkThemeTest() {
const [darktheme, setDarkTheme] = useContext(ThemeContext);
return (
<Button onClick={() => {
setDarkTheme(!darktheme);
}}>
Theme: {darktheme && "Dark" || "Light"}
</Button>
)
}
First, define a type for your context value
import { createContext, Dispatch, SetStateAction } from "react";
interface ThemeContextType {
darkTheme: boolean;
// this is the type for state setters
setDarkTheme: Dispatch<SetStateAction<boolean>>;
}
Then, create your context with this type and initialise it with a default value. This might seem unnecessary but it will avoid checking for null or undefined context later on
export const ThemeContext = createContext<ThemeContextType>({
darkTheme: false,
setDarkTheme: () => {}, // no-op default setter
});
Once you have created your state value and setter, set them into the context provider value
<ThemeContext.Provider value={{ darkTheme, setDarkTheme }}>
Now you can destructure the context value easily via useContext with full type support
const { darkTheme, setDarkTheme } = useContext(ThemeContext);
You could continue to use your array format though I wouldn't recommend it.
type ThemeContextType = [boolean, Dispatch<SetStateAction<boolean>>];
export const ThemeContext = createContext<ThemeContextType>([false, () => {}]);
and
<ThemeContext.Provider value={[darkTheme, setDarkTheme]}>
I have a problem with reading {find}.
The problem is in ProductDetail.js.
First, click on the products link than on any product to see details.
TypeError: Cannot read properties of null (reading 'find')
https://codesandbox.io/s/react-router-product-detail-pages-dynamic-links-forked-y1o0n?file=/src/ProductDetail.js:418-429
You've done some mistakes over there in your ProductDetail.js file.
First:
You can use useEffect hook to check and compare if there is a matching id or not.
Second:
You can use useState hook to store the thisProduct and update the thisProduct value by calling setThisProduct and use it in the JSXElement.
This is always a best practice to use the state for data set and get.
Here is more about React.Hooks
Third:
Price is a Object and you can't render your object like that, so use the key instead of object while rendering. like this: {thisProduct?.price?.current?.value}
You can learn more about optional chaining
Fourth:
productId which you're getting from useParams is a string type, and your productId from sneakers is a number type. So you need to change your productId to number while comparing like this: Number(productId)
Learn about Numbers in Js
Here is the complete code of yours:
// ProductDetail.js
import React, { useContext, useEffect, useState } from "react";
import { useParams } from "react-router-dom";
import { StateContext } from "./GlobalContext";
function ProductDetail() {
const { productId } = useParams();
const { sneakers } = useContext(StateContext);
const [thisProduct, setThisProduct] = useState({});
useEffect(() => {
if (sneakers) {
const findProduct = sneakers.find((product) => {
return product.id === Number(productId);
});
console.log("findproduct", findProduct);
setThisProduct(findProduct);
}
}, [productId, sneakers]);
return (
<div>
{thisProduct && (
<>
<h1>{thisProduct?.name}</h1>
<p>Price: {thisProduct?.price?.current?.value}</p>
<p>{thisProduct?.description}</p>
</>
)}
</div>
);
}
export default ProductDetail;
completely check your state and props, it is not providing valid data to child component
<StateContext.Provider value={{ sneakers }}>
{console.log(sneakers, "== thisProduct")}
{children}
</StateContext.Provider>
console will show your data, it coming null so that is the issue
I have this component, which works fine, but only once. If I reload, I have a undefined error.
My component :
import { UidContext } from "../components/AppContext"
import React, { useContext, useEffect, useState } from "react"
import axios from "axios"
export default function Balance() {
const uid = useContext(UidContext)
const [userWallet, setUserWallet] = useState(null)
useEffect(() => {
if (uid !== null) {
axios.get(`${process.env.REACT_APP_API_URL}api/balance/${uid}`)
.then((res) => setUserWallet(res.data[0]))
}
}, [uid])
return (
<section>
{userWallet.salaire1}
</section>
)
}
The result at first load :
userWallet result
and then, I have this error :
TypeError: Cannot read property 'salaire1' of null
Why would a console.log work, and not in the JSX ?
Thank you
You can use optional chaining with userWallet?.salaire1 . or handle with ternary conditional like
userWallet.salaire1 && userWallet.salaire1
In this case you have predefined state value userWallet is null. hence the UI couldn't render undefined property therefore your screen is blank and promp error
actually your console work but it the log return twice, the first one is null then the data shown.
I hope my answer can help to understand your issue :)
I am trying to print the value of props in my JSX,even though the logs show the object when i try to print individual objects it throws error TypeError: Cannot read property <'objects'> of undefined
i am using REDUX, i tried looping using map, forEach etc. still i am getting the error. console.log("props.stories") shows the objects but when i try to log individual objects the "props.stories" becomes "undefined"
import React from 'react'
import {connect} from 'react-redux'
import {Link} from 'react-router-dom'
const ShowStory = (props) => {
console.log(props.stories) // shows objects
console.log(props.stories._id) // gives error and above log becomes undefined
return(
<div>
<h1>{props.stories.bookTitle}</h1>
</div>
)
}
const mapStateToProps = (state, props) => {
const id = props.match.params.id
var arr1d = [].concat(...state.stories)
return {
stories: arr1d.find(story => story._id == id),
}
}
export default connect(mapStateToProps)(ShowStory)
If stories is an array of objects, you need to access it using .map function like this.
Remove this line to get rid of console error:
console.log(props.stories._id) // gives error and above log becomes undefined
If you want to print all stories' bookTitle then:
<ul>
{props.stories.map((story, index) => (
<li key={index}>{story.bookTitle}</li>
))}
</ul>
If you want to print first story's bookTitle then:
<div>
<h1>{props.stories[0].bookTitle}</h1>
</div>
I'm using React and Redux to build a website and I have the code below for AppInfo component. I have result variable in the render method which is initialized before return statement. At first the result is an empty string but once the state changes it is set to an object which contains various app attributes. I want to display the result variable inside a div. The result always stays an empty string although I do see that the redux state is updated. In addition if call directly this.props.appId inside the div the updated state is indeed displayed. Why the result variable doesn't work?
This is my code:
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import { connect } from 'react-redux';
class AppInfo extends Component {
render() {
const { appInfo } = this.props;
const { appId } = appInfo;
let result = '';
if (appId) {
result = JSON.stringify(appInfo);
}
return (
<div>
{result}
{`JSON.stringify(appInfo) = ${JSON.stringify(appInfo)}`}
{`this.props = ${JSON.stringify(this.props.appInfo)}`}
</div>
);
}
}
AppInfo.propTypes = {
appInfo: PropTypes.object.isRequired
};
const mapStateToProps = state => ({
appInfo: state.app
});
export default connect(mapStateToProps, null)(AppInfo);
Could you try to use result = JSON.stringify(this.props.appInfo);?
I think the issue might be related to the first 2 const’s you create.