React/JSX - map property not found in object - reactjs

Im new to react framework. I'm facing an issue and need some help here.
An API call will result in an object which has several object rows.
I wanted to use map on that object to render the div's.
export default class SearchResult extends Component {
static propTypes = {
courses:React.PropTypes.object,
}
render() {
....
this.props.courses.map( entity => renderEntity(entity));
...
}
}
I'm having an error stating map is not a property. After searching in google i found object doesnt have map property. Only arrays have it.
Can some one help me
1) How do i get map functionality / equivalent. All I want to do is render a set of html tags for every element in the object. this is to develop a search result.
2) Can I convert object to arrays. Is that required.
3) if (this.props.courses) is always turning out to be true because it has proto initialised. In that case how will I check if courses really has data. courses.length etc didnt work as it doesnt have any property of length nor it is an array.
Object console log output
Note :- this is my first question in stackoverflow. So kindly ignore if you find any error.
Thanks in advance for help.
Sesh

More than a React problem this is a pure JS one. If your need is to cycle through the values of the object, then something like this should work just fine:
Object.keys(this.props.courses).map(course => renderEntity(this.props.courses[course]))
As a suggestion for future issues like this, always start looking here, in this specific case this, is the ideal like for your problem.

Related

Mobx async example does not render result after action

You can look at the issue via codesandbox
Codesandbox: https://codesandbox.io/s/great-frog-m2s7h
Context
I am trying to fetch some data and populate some variable and render the value in React, essentially following the documentation await/async + runInAction example: https://mobx.js.org/actions.html#asynchronous-actions
However, when the data is fetched, React actually does not re-render. However, if you edit the text in there(i.e. change hi to his or whatever, then you see the correct value appear.
Problem
What exactly am I doing wrong with the data fetching? Why isn't the observable value not being re-rendered correctly when its been assigned a value after some data has been fetched?
This is actually one of the limitations of Mobx.
From the docs:
make(Auto)Observable only supports properties that are already defined. Make sure your compiler configuration is correct, or as workaround, that a value is assigned to all properties before using make(Auto)Observable. Without correct configuration, fields that are declared but not initialized (like in class X { y; }) will not be picked up correctly.
Just initialize the title this.title=undefined and it will work.
Its a simple mistake. MobX can not compare data of title to something that dosent exist. Stuff should have default value of some sort, even a null. hence in a constructor you need to define title default value like
constructor() {
this.title = [],
makeAutoObservable(this);
}
or, if you wish, even null
constructor() {
this.title = null,
makeAutoObservable(this);
}
Basiclaly, whenever you create some observable variable in a store - you need to define its default value in a constructor above makeAutoObservable.
Here, a forked project of yours with juswt this 1 line change to make it work https://codesandbox.io/s/suspicious-noether-fnhjw

cannot read property of 'map' undefined - typescript react

I'm trying to create a simple app with react using typescript, its my first time using typescript with context api and to this level so I'm having issues I don't quite understand. my main issues is my .map doesn't seem to me working and for some reason and gives me the error I provided in the title and when I click the Add catergory button in the Main.tsx file nothing seems to work there either? Any ideas? I've created a sandbox below.
Any help would be appreciated please, thank you.
https://codesandbox.io/s/smoosh-violet-j1gjz?file=/src/components/CategoryList.tsx
Your error simply mean that "state" is undefined.
const { state } = useContext(Store) || [];
Mean that you want to extract the property named state from the result of "useContext(Store) || [];"
In the case where you have an empty Array it make no sens, you array will not have a property state. So you can change by
const state = useContext(Store) || [];
I dont know what "useContext(..)" is suppose to return, but at least it correct the error when you have an empty array

Using custom html element in react

I am using Typescript and REACT and I want to utilize and wrap some custom html elements in my TSX. For example, I am using a library with a customer html element called ch5-button an it is used in a vanilla html file as such
<ch5-button class="shadow-pulse-button" type="default" shape="circle" label="" iconClass="fas fa-award">
</ch5-button>
I did a ton of searching, but seems like i am not even smart enough to get the search correct to find how to do this. I am not even sure if I have the correct import statement to get those elements -- the closest I got was :
declare var CrComLib: typeof import('#crestron/ch5-crcomlib');
...
const ch5Button = new CrComLib.Ch5Button();
console.log("ch5Button");
console.log(ch5Button);
The console.log display <ch5-button></ch5-button> soI have no idea if I am even on the right track to using this thing. The ch5Button is a class with a lot of methods that look pretty much like what an html element would have but I just dont know what to do with it and how to learn a method for using it. I found some sites that explain how to use observables and such but I am sketchy on if I am heading down the right path. I have attached am image of what some if the properties and methods of the ch5Button looks like in chrome debugger.
Can anyone point me in the right direction? I would create a REACT component that wraps this class and can use props to set the correct attributes etc.
I am very comfortable building REACT apps but admittedly, I am not an advanced developer with it yet but doing my best to learn.

Why "selected" not rendered here?

I am trying to understand how React works with the new Hooks implementation. In this example, I want the browsers to render selected items as I click on the rendered options. But as you can see, it doesn't work.
Here is the example: https://codesandbox.io/s/pjorxzyrx7
Do I have to use the useEffect in this case? Also, as I understand, useEffect couldn't render anything and only return functions. So, what am I missing here?
Thank you!
You're currently mutating the contents of the selected array instead of replacing it. React can't detect a state change when you do this.
Try something like the following:
const handleSelected = item => {
console.log(item);
console.log(selected);
setSelected([...selected, item]);
};
When updating arrays or objects as a part of a state, always make a new copy to assign so that React can properly know when to re-render.
Also, include relevant parts of your code directly in the question in the future, instead of hiding it behind a link (although including a runnable example is great!)

Accessing a property from an array of objects stored in state in React

I'm working with ReactJS on a project and using KnexJS to access a database. I would like to store and use the JSON objects I retrieve, in the state of a component as something along the lines of the following.
this.setState({tutors: tutors}) //Retrieval from database after promise
and then access their properties like so
this.state.tutors[0].email
this.state.tutors[0].firstname
However, when I try this, I get the following error
TypeError: Cannot read property 'email' of undefined
I have checked the console.log as well as using JSON.stringify to determine if the objects are retrieved by the time I need them. And it appears that they are. I simply cannot access their properties from state.
Is there something I can do about this? Or do I need to retrieve them from the DB one by one?
This could be happening, because at the moment your code tries to retrieve data from state, the data is not there yet -- though it's possibly added later. This is something that happens quite often, in my experience. You should probably check that an object exists, before trying to access a property on it -- and return null or undefined in case it doesn't exist:
this.state.tutors[0] ? this.state.tutors[0].email : null
EDIT (in response to the additional code samples):
Assuming your fetch function works ok and adds the fetched data to state (I would use forEach instead of map to push the elements into the array, or just map over the fetched array and add that to the state directly, without an intermediary array/variable/push -- but I think your code should work)...
The problem has to do with the render method, since when the component renders initially the data is not yet in state, and as such you're passing an empty array to the TutorTable component, which probably in turn produces the error you see.
The data gets added to state later, but at this stage the error on the initial render has already happened.
You could solve this by rendering the TutorTable conditionally, only when the data gets added to the state:
<div className="col-7">
<h3> My Tutors </h3>
{this.state.tutors.length > 0 && <TutorsTable tutors={this.state.tutors} />}
</div>
if you console.log out this.state.tutors in the render() method you should see in the console an empty array ([]) returned on the initial render, and then an array filled with data when the component re-renders when the data is added to the state.
I hope this helps.
It appears to me you are trying to get the first element of an array this.state.tutors[0].email
is the tutors really an array,could provide the format of the data that you console logged as you stated.This probably should be in the comment section but I have less than 50 rep so i cant comment.
you should check first tutors. if you are getting tutors an array then you can access its first element.
if(this.state.tutors[0]) {
console.log("first element of tutors array", this.state.tutors[0].email)
// anything you can acccess now of this element
}
and assign first tutors as an empty array in state.
state = {
tutors: []
}
in first lifecycle you have no data in this.state.tutors[0]
for this reason first check this.state.tutors[0] is ready or not like this
if(this.state.tutors[0])
{
var data=this.state.tutors[0];
data.push('your data');
this.setState({tutors:data})
}

Resources