Error while using if statement inside Map reactJS - javascript

I am new to reactJS. I am implementing a Quiz page, where users can answer the questions and once they submit answers, the result is displayed. Following is the DisplayResult component which calculates the score and displays the result. I am getting error at the if statement. Checked the syntax multiple times, not sure if it is a syntax issue or if I am missing something. Could you please help.
import React from "react";
function DisplayResult(props) {
var score=0;
var Answers=[1947,1950];
props.data.map((dat, i) =>
({if (dat===Answers[i]) {score++}}
));
return<div>Your answers are {props.data[0]}, {props.data[1]} and your score is {score} </div>;
}
export default DisplayResult;
Below is the error I am getting:
./src/DisplayResult.jsx
Line 8:14: Parsing error: Unexpected token, expected ","
6 | var Answers=[1947,1950];
7 | props.data.map((dat, i) =>
8 | ({if (dat===Answers[i]) {score++}}
| ^
9 | ));
10 | returnYour answers are {props.data[0]}, {props.data[1]} and your score is {score} ;

Use a forEach loop instead of .map.
By the way, you need to focus on the basics and fundamentals of React.
Try going through basic tutorials on Youtube.
const Answers = [1947, 1950];
function DisplayResult(props) {
let score = 0;
props.data.forEach((data, i) => {
if (data === Answers[i]) {
score += 1;
}
});
return (
<div>
Your answers are {props.data[0]}, {props.data[1]} and your score is{" "}
{score}{" "}
</div>
);
}

You have an extra parentheses on your map, it should be like this:
props.data.map((dat, i) => {
if (dat === Answers[i]) {
score++
}
})
You should use a forEach instead of a map since you're suppose to have a return value in a map which is not the case here. See documentation here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map

You shoould not be using parenthesis and using the curly braces inside of it, it seems that you are used to conditional rendering notation:
props.data.map((dat, i) =>
(
{if (dat===Answers[i]) {score++}}
)
);
write this instead:
props.data.map((dat, i) =>
{
if (dat===Answers[i]) {score++}
}
);

Use foreach instead of map since you're not returning anything. And you're wrapping all you if statement inside ( ) which makes means map method is trying to return the whole thing and will throw an error.
props.data.forEach((dat, i) => {
if (dat === Answers[i]) {
score++
}
})

Related

how to get to the key in an array of objects?

I hope you are all well 🙂
I would like to ask something that (I hope) is basic, i have this function that is responsible for returning the filtered objects with a specific "key" variable that translates to color or size.
Well I put the color and size variables inside an array of objects, I would like to know what is the terminology I have to use now in my "item[key]" to be able to get to my "color" variable as shown in the last picture 😦
picture showing what key im able to get now and then what key im looking to get!
Thanks in advance for any and all help, have a nice day!
here is the code for the two functions used in this process:
const [filtros,setFiltros] = useState({});
const gerirFiltros = (evento) =>{
const valor = evento.target.value;
console.log(evento.target.name + evento.target.value)
if (evento.target.name === "cor" ) {
const cor = evento.target.name
setFiltros( {
...filtros,
["variacoes"]:[{
[evento.target.name]:valor
}],
})
}
else {
setFiltros({
...filtros,
[evento.target.name]:valor,
}) // THIS IS JUST TO PASS TO PAGE #2 (https://pastebin.com/4GH3Mi3H) THE VARIABLE `filtros` THAT IS AN ARRAY WITH MANY FILTERS LIKE -> {marca:"Paz rodrigues"}, etc..
And the functio that receives the filter ( the one i think i need to change) :
useEffect(() => {
categoria &&
setProdutosFiltrados(
produtos.filter((item) =>
Object.entries(filtros).every(([key,value],i) =>
//console.log("key ->" + key + "value->" + value[0].cor) )
item[key].includes(value)
)
)
)
You can use some()
useEffect(() => {
categoria &&
setProdutosFiltrados(
produtos.filter((item) =>
Object.entries(filtros).every(([key,value],i) =>{
//Here the value is an array 'variacoes' so to check colors use filter to get all the elements of 'variacoes' array;
//Also assuming that the color you are passing will be available here as item[key]
var allColors = item.map(i=>i.cor)
return value.some((val)=>allColors.includes(val.cor))
}
)
)
)

problem mixing material-ui elements and code in react javascript

I constantly have issues trying to use code and material-ui elements in react jsx code. Here's a code snippet:
const icols = 0;
const makeTableRow = (
x,
i,
formColumns,
handleRemove,
handleSelect) =>
<TableRow key={`tr-${i}`}>
{formColumns.map((y, k) => (
y.displayColumn ? (<TableCell key={`trc-${k}`}>{x[y.name]}</TableCell>) : null), <-comma added for next line
y.displayColumn ? (cols+=1) : null)
)}
<TableCell>
<IconButton onClick={() => handleSelect(i)} ><EditIcon fontSize='small'/></IconButton>
<IconButton onClick={() => handleRemove(i)} ><DeleteForeverIcon fontSize='small' /></IconButton>
</TableCell>
</TableRow>
I am getting a jsx parsing error, when I add this line above:
y.displayColumn ? (cols+=1) : null)
If I remove the comma at the EOL above it, I still get an error. Basically I can't get a map to exec more than one statement.
If I take out the line and the EOL comma above it, everything works but I don't get a displayed column count, which I require.
I've tried using simple if/else which I am more comfortable with, but I have NEVER been able to get if/else to work in a jsx function. I want to only create a tablecell for a column w/displayColumn flag set to true, and I want a total count of the displayed columns, so I can use it later on (cols).
Is there a way to accomplish this with an if/else statement? Then I can have more than 1 statement in the if clause. The ternary operator only allows 1 statement, and I can't find anywhere what maps limitations are.
Thanks in advance for your help!
You can do something like this. You can open the open the arrow function body in map and put return JSX and do the cols increment there. Instead of having two ternary operator checks for the same condition, we can have just one conditional statement.
<TableRow key={`tr-${i}`}>
{
formColumns.map((y, k) => {
if (y.displayColumn) {
cols += 1;
return <TableCell key={`trc-${k}`}>{x[y.name]}</TableCell>
}
return null
})
}
<TableCell>
<IconButton onClick={() => handleSelect(i)} ><EditIcon fontSize='small'/></IconButton>
<IconButton onClick={() => handleRemove(i)} ><DeleteForeverIcon fontSize='small' /></IconButton>
</TableCell>
</TableRow>
Basically I can't get a map to exec more than one statement.
You can't execute more than one expression inside a arrow function definition, instead use regular declarated functions
{formColumns.map((y, k) => {
y.displayColumn ? (cols+=1) : null;
// Return what you want to render
return y.displayColumn ? (<TableCell key={`trc-${k}`}>{x[y.name]}</TableCell>) : null
}}
There are only two types of arrow function
arrow_function = () => "i will be returned"
// This way you declare only one expression after the arrow and it is returned
and
arrow_function = () => {
// This is a regular logic function
text = "i will be" + " returned";
return text;
}
EDIT 1: Add conditionals between JSX
There are two ways i know to do it
const App = () => {
return (
<div>
<h2>First form</h2>
<FirstForm true={true} />
<hr />
<h2>Second form</h2>
<SecondForm true={false} />
</div>
)
}
const FirstForm = props => {
// This way is just a ternary conditional
return (
<div>
{props.true
? <span className="success">True condition matched</span>
: <span className="danger">False condition matched</span>
}
</div>
)
}
const SecondForm = props => {
// This way uses a anonymous function executed in runtime
return (
<div>
{(() => {
let message = "Hello";
message += " World, from an auto executed anonymous function";
return (
<span className={props.true?"success":"danger"}>{message}</span>
)
})()}
</div>
)
}
ReactDOM.render(
<App />,
document.getElementById("react")
);
.success {
color: darkgreen;
}
.danger {
color: #5e181b;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="react"></div>
Ok psiro, so I looked at your examples, which all work in your situation. However, as soon as I apply one to my scenario, I still get a syntax error. Like here:
<TableBody>
{(() => {
console.log('data = ' + JSON.Stringify(data, null, 2) + '.'));
return ((data.length > 0) ? (
data.map((x, i) => row(
x,
i,
formColumns,
handleRemove,
handleSelect,
editIdx
))) : (<TableRow><TableCell colSpan={`${cols}`}>No Data</TableCell></TableRow>) )
})()}
</TableBody>
And this is the problem I have w/anonymous functions. They create unmaintainable code. I am not doing anything different than your example. Just TWO js statements inside the code you presented. Your code works, mine returns a syntax error.
And why do I even NEED a double-anonymous function to have 2 simple js statements inside an if statement? Why does your code work, and mine not?
Addendum:
Ok, so I made some inferences based on your code and realized I had added yet ANOTHER anonymous function (the map statement) into the code. I reworked it into this, which compiled:
{(() => {
console.log('data = ' + JSON.Stringify(data, null, 2) + '.');
if (data.length > 0) {
return (data.map((x, i) => row(x, i, formColumns, handleRemove, handleSelect, editIdx)))
}
return(<TableRow><TableCell colSpan={`${cols}`}>No Data</TableCell></TableRow>)
})()}
The fact that it looks completely unmaintainable is irrelevant I guess. But it doesn't matter because it STILL doesn't work! Now I get a 'JSON.stringify is not a function' at runtime, which is ridiculous of course. Why can't I get a simple console.log to work in reactjs?
ADDENDUM:
Ok, I fixed the issue thanks to all the help. For anyone else that has an issue w/multiple statements inside an anonymous function, if you want to do it, you need to add a return statement so the function knows what result to return.
<TableBody>
{(() => {
console.log('data = ' + data + '.');
if (data.length > 0) {
return (data.map((x, i) => row(x, i, formColumns, handleRemove, handleSelect, editIdx)))
}
return(<TableRow><TableCell colSpan={`${cols}`}>No Data</TableCell></TableRow>)
})()}
</TableBody>
That includes when you have an anonymous function inside another anonymous function. Hope this helps anyone else having this problem.

Where did I make the mistake of changing my search filter? And how to fix it?

I have a list of airplanes departing or arriving at the airport and i also had a search filter where i enter the time of arrival or departure and filtering of the airplanes. I do this using the actual property of my API. But I needed to change my search. Now I need to search by flight number - the planeTypeID.code property of my API. But when I changed it, stopped showing a list of airplanes. What is my mistake and how to fix it?
I just instead actual everywhere wrote ["planeTypeID.code"] and delete method:
.split("-").reverse().join("-")
OLD version:
small part airplane.js(reducer)
case "RUN_FILTER":
var newData = state.data[action.shift || state.shift].filter(x => {
return (
x.actual &&
x.actual.includes(
state.day
.split("-")
.reverse()
.join("-")
)
);
});
case "LOAD_DATA_END":
var newData = action.payload.data[state.shift].filter(x => {
return (
x.actual &&
x.actual.includes(
action.payload.day
.split("-")
.reverse()
.join("-")
)
);
});
small part app.js(main component)
export function searchFilter(search, data) {
return data.filter(n => n.actual.toLowerCase().includes(search));
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
NEW version:
small part airplane.js(reducer)
case "RUN_FILTER":
var newData = state.data[action.shift || state.shift].filter(x => {
return (
x["planeTypeID.code"] && // Сhange
x["planeTypeID.code"].includes( // Сhange
state.day
// delete
)
);
});
return Object.assign({}, state, {
case "LOAD_DATA_END":
var newData = action.payload.data[state.shift].filter(x => {
return (
x["planeTypeID.code"] && // Сhange
x["planeTypeID.code"].includes( // Сhange
action.payload.day
// delete
)
);
});
small part app.js(main component)
export function searchFilter(search, data) {
return data.filter(n => n["planeTypeID.code"].toLowerCase().includes(search)); // Сhange
}
All project code in sandbox:
https://codesandbox.io/s/redux-ant-design-filter-table-column-with-slider-jj6mu
An example value of x["planeTypeID.code"] is "B734", of state.day "23-08-2019" => those are 2 different fields => you will get an empty array when you filter by x["planeTypeID.code"].includes(state.day) ¯\_(ツ)_/¯
After debugging via comments, the most likely solution is:
x["planeTypeID.code"].toLowerCase().includes(action.search || state.search)
I recommend to Get Started with Debugging JavaScript as a generic first step to questions that start with:
Where did I make the mistake...
...before posting to Stack Overflow.

React single line component

Hello I have a component which doesnt return anything. Im following a tutorial and the person is using newer syntax which confuses me a bit. The component looks like this:
const Alert = ({alerts}) => alerts !== null && alerts.length > 0 && alerts.map(alert => (<div key={alert.id} className={`alert-${alert.type}`}>{alert.msg}</div>));
I simply want to know how to write this without it being single line. So i can see what's going on. Much appreciated in advance. For as far as i am aware you always need to return something.
const Alert = ({ alerts }) => {
if (alerts !== null && alerts.length > 0) {
return alerts.map(alert => (
<div key={alert.id} className={`alert-${alert.type}`}>
{alert.msg}
</div>
));
}
return null
};
Things at play here are:
Arrow Functions
Array.Map
JSX
Template Literals
Basically its a component that takes in an alerts property (Array) as a prop (<Alert alerts={[...]} />). It checks whether the passed array is present and is not empty and then maps over it. For every item in the array, we are rendering a div containing the alert message.
Hope this helps!
Very roughly (i.e., untested):
const Alert = ({alerts}) => {
if ((alerts === null) || (alerts.length === 0)) {
return null
}
return alerts.map(alert => (
<div
key={alert.id}
className={`alert-${alert.type}`}
>
{alert.msg}
</div>
))
}
const Alert = ({alerts}) => {
if (!alerts || !alerts.length) return null
return (
<>
{alerts.map(alert => (
<div key={alert.id} className={`alert-${alert.type}`}>{alert.msg}</div>
)}
</>
)
}
I think what you are struggling with is generally the one-liner syntax, which doesn't need a return if there are no braces present.
What I mean is that this line
return alerts.map(alert => {
return (<div key={alert.id} className={`alert-${alert.type}`}>{alert.msg} </div>)
})
Would be the same as this line
return alerts.map(alert => (<div key={alert.id} className={`alert-${alert.type}`}>{alert.msg} </div>))

Looping through a Map in React

I have a Map object:
let dateJobMap = new Map();
for (let jobInArray of this.state.jobs) {
let deliveryDate: Date = new Date(jobInArray.DeliveryDate);
let deliveryDateString: string = deliveryDate.toLocaleDateString("en-US");
if (dateJobMap.has(deliveryDateString)) {
let jobsForDate: IDeliveryJob[] = dateJobMap.get(deliveryDateString);
jobsForDate.push(jobInArray);
}
else {
let jobsForDate: IDeliveryJob[] = [jobInArray];
dateJobMap.set(deliveryDateString, jobsForDate);
}
}
In my render method, I want to call a TruckJobComp object for each delivery job in the value's array to display it:
<div className={ styles.column }>
<p className={ styles.description }>{escape(this.props.description)}</p>
{
dateJobMap.forEach(function(jobsForDate, dateString) {
jobsForDate.map(job => (
<TruckJobComp job = { job } />
))
})
}
</div>
This seems like it should work but doesn't. It never creates a TruckJobComp. I do a .forEach iteration on my Map, and for each value's array, I use .map to get the individual job object to send to TruckJobComp object.
When I create a temp array to grab the jobs from the last loop:
let tempJobs: IDeliveryJob[];
and in the loop add in:
if (dateJobMap.has(deliveryDateString)) {
let jobsForDate: IDeliveryJob[] = dateJobMap.get(deliveryDateString);
jobsForDate.push(jobInArray);
tempJobs = jobsForDate;
}
and then use that array in the render:
<div className={ styles.column }>
<p className={ styles.description }>{escape(this.props.description)}</p>
{
tempJobs.map(job => (
<TruckJobComp job = { job }/>
))
}
</div>
It displays as expected.
I do have a warnings in Visual Studio Code:
Warning - tslint - ...\TruckDeliverySchedule.tsx(104,38): error no-function-expression: Use arrow function instead of function expression
I don't know enough to understand. Line 104 corresponds with:
dateJobMap.forEach(function(jobsForDate, dateString) {
I am very new to this so I'm not 100% sure how most of this works. Just trying to put pieces I've learned together to get things to work.
Second Edit:
{escape(this.props.description)}
{
[...dateJobMap.keys()].map(jobsForDate => // line 154
jobsForDate.map(job => (
<TruckJobComp job = { job } />
))
)
}
Produces error:
[09:06:56] Error - typescript - src\...\TruckDeliverySchedule.tsx(154,27): error TS2461: Type 'IterableIterator<any>' is not an array type.
dateJobMap.forEach(...) returns undefined, so it cannot be mapped to a collection of elements.
ES6 maps have forEach method for compatibility purposes (generally for..of is preferred to iterate over iterables) and don't have map method. A map should be converted to array first, then it could be mapped to an element. Since values aren't used, only keys need to be retrieved:
{
[...dateJobMap.keys()].map(jobsForDate =>
jobsForDate.map(job => (
<TruckJobComp job = { job } />
))
)
}
All this warning is saying is that instead of using the syntax function(jobsForDate, dateString) {} you should use the syntax (jobsForDate, dateString) => {}.
The reason could be the way this is scoped in arrow functions versus function expressions. See this post.
My guess as to the reason your first approach didn't work but your second one did is that forEach doesn't actually return an array, and if it did, calling map within forEach would return an array of arrays (but, again, it doesn't). Not sure how React would handle that, but React does know how to handle a single array, which is what your last approach returns.

Categories