Adding parent div's inside .map - javascript

Is there any way I can include the wrapping div's FilterListContainer, FilterListScroll and FilterList in the map itself?
So if there is something to map, it will add the parent div's. If not it wont.
<FilterListContainer>
<FilterListScroll>
<FilterList>
{Object.keys(this.props.body_search_filter)
.map((k) => (
<SidebarFilter
key={k}
type={k}
filter={this.props.body_search_filter[k]}
handleChange={this.handleFilterChange}
/>
))
.filter(
(i) =>
i.props.filter.list.length > 0 &&
((!i.props.filter.optional && !i.props.filter.hidden) ||
(i.props.filter.list.length !== 1 &&
!i.props.filter.list[0].disabled))
</FilterList>
</FilterListScroll>
</FilterListContainer>

You'll be able to use short-circuiting of logical operators here:
{Object.keys(this.props.body_search_filter).length && (
<FilterListContainer>
<FilterListScroll>
<FilterList>
{Object.keys(this.props.body_search_filter)
.map((k) => (
<SidebarFilter
key={k}
type={k}
filter={this.props.body_search_filter[k]}
handleChange={this.handleFilterChange}
/>
))
.filter(
(i) =>
i.props.filter.list.length > 0 &&
((!i.props.filter.optional && !i.props.filter.hidden) ||
(i.props.filter.list.length !== 1 &&
!i.props.filter.list[0].disabled))
</FilterList>
</FilterListScroll>
</FilterListContainer>
)}
But you might want to filter the list, then check if the filtered list has any elements instead:
const filtered = Object.keys(this.props.body_search_filter).filter((k) => {
const f = this.props.body_search_filter[k];
return f.list.length > 0 &&
((!f.optional && !f.hidden) ||
(f.list.length !== 1 && !f.list[0].disabled))
});
// ...
// then use 'filtered' instead
{filtered.length && (
<FilterListContainer>
<FilterListScroll>
<FilterList>
{filtered.map((k) => (
<SidebarFilter
key={k}
type={k}
filter={this.props.body_search_filter[k]}
handleChange={this.handleFilterChange}
/>
))}
</FilterList>
</FilterListScroll>
</FilterListContainer>
)}

Moving my comment to an answer to add a snippet
You could do the map before the return. Then you can 'check' if the map has some content, if so, use it, otherwise, don't render (or use fallback)
Please see comments in code
const { useState } = React;
const Example = () => {
// Demo data
const [data, setData] = useState([ 'foo', 'bar' ])
// Filter + Mapping logic
const mapped = data
.filter(d => d !== 'foobar')
.map(d => <li>{d.toUpperCase()}</li>);
// Content based on map, use it, or render 'null'
// The wrapped 'ul' is OP's FilterListContainer as an example
const content = !mapped.length ? null :
(
<div>
<ul>
{mapped}
</ul>
</div>
);
// Render
return content;
}
ReactDOM.render(<Example />, document.getElementById("react"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="react"></div>

Related

How to render a component for particular element in a array

I have an array, for which a component (<span>Delete</span> in my case) needs to be shown only if the array length is greater than 2 and also, not show in first two array elements but show in other elements.
Example:
array = ["One","Two","Three","Four"]
Show <span>Delete</span> in "Three" and "Four" as the array is greater than length 2.
In the above case, even if the array is greater than length 2 don't show in first two elements ( "One" and "Two" ).
Code:
const App = () => {
const [element, setElement] = useState(["element"]);
return (
<>
{element.map((e) => (
<div>
<span>{e}</span>
{element.length > 2 && <span style={{color:"red"}}>{" "}Delete</span>}
</div>
))}
<button onClick={() => setElement((element) => [...element, "element"])}>Add</button>
</>
);
};
The above code shows "Delete" text in all the elements
instead should show only for elements after the 2nd index.
CodeSandbox: https://codesandbox.io/s/basic-antd-4-16-9-forked-2w3lg5?file=/index.js:98-478
Use the index of the element you're iterating over (the second argument in the .map callback) to check if the index is 2 or more - if so, you can show the delete, otherwise don't show it.
const App = () => {
const [elements, setElements] = useState(["element"]);
return (
<>
{elements.map((e, i) => (
<div>
<span>{e}</span>
{elements.length > 2 && i >= 2 && <span style={{color:"red"}}>{" "}Delete</span>}
</div>
))}
(Because the state is an array, making its name plural makes a lot more sense than a singular element, which sounds like an array item)
You also need to check if the index of the current item is greater than 1.
const App = () => {
const [element, setElement] = React.useState(["element"]);
return (
<React.Fragment>
{element.map((e, i) => (
<div>
<span>{e}</span>
{i > 1 && element.length > 2 && <span style={{ color: "red" }}>Delete</span>}
</div>
))}
<button onClick={() => setElement((element) => [...element, "element"])}>
Add
</button>
</React.Fragment>
);
};
ReactDOM.render(<App />, document.getElementById("root"));
<script crossorigin src="https://unpkg.com/react#17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom#17/umd/react-dom.development.js"></script>
<div id="root"></div>
You can do something like this
{element.length > 2 && element.map((ele,index) => {
if(index > 1){
return <p>{ele}</p>
}
else{
return <></>
}
})}
You need to access the current index of the current element (e), so include that in the parameter list of map().
Secondly, the condition to check if the index (idx) is greater than or equal to (>=) 2.
const App = () => {
const [element, setElement] = useState(["element"]);
return (
<>
{element.map((e, idx) => (
<div>
<span>{e}</span>
{element.length && idx >= 2 && <span style={{color:"red"}}>{" "}Delete</span>}
</div>
))}
<button onClick={() => setElement((element) => [...element, "element"])}>Add</button>
</>
);
};

I want to show the filtered search from an array, I cannot return it in front end

I want to display the Project Name and other indexes from filteredResults, how can I map it and its indexes? Or parsing?
I put it on onClick event:
function filter() {
var filteredResults = projectData.filter((f => f.ProjectName.includes(filterKeyword) && (f => f.PartitionKey.includes(nameArea))));
console.log(filteredResults);
};
return:
<Stack direction="row" id="projectResults">
<Masonry columns={2} spacing={2}>
{!!projectData && (
projectData.map((card, index) => (
<MasonryItem key={card.RowKey}>
...
</MasonryItem>
))
)}
</Masonry>
</Stack>
Your filter callback is not valid.
Try changing it to this:
var filteredResults = projectData.filter(f => f.ProjectName.includes(filterKeyword) && f.PartitionKey.includes(nameArea));

How can I update the props.data from a child component?

I am trying to display a range from an array that is being passed into a child.
My current Parent component is as follows:
import data from './data.json'
return (
<Cell symbol={data.symbol} number={data.number} />
)
And that data is being passed into my Child component:
const [updatedSymbols, setUpdatedSymbols] = useState()
useEffect(() =>
if(props.number === 1 || props.number === 2 || props.number === 3 ){
setUpdatedSymbols(props.number)
console.log("updated: " + props.number)
}
}, [props.symbol])
return (
<div class="cell">
{updatedSymbols}
</div>
)
QUESTION: If you look at the useEffect, you will notice that within the if-statement, I am selecting the numbers I want and simply passing them into the useState, "setUpdatedSymbols".
My problem is that there are too many numbers that I need to select, about 100, how can I push them all into updatedSymbols without using || ?
whatever the numbers list you want to check before you insert into your state you can collectively do this
const [updatedSymbols, setUpdatedSymbols] = useState()
const range = (from, to ) => {
var collection = [];
for(let i = from; i<=to ; i++) {
collection.push(i);
}
return collection;
}
useEffect(() =>
if(range(1,100).includes(props.number) ){
setUpdatedSymbols(props.number)
console.log("updated: " + props.number)
}
}, [props.symbol])
return (
<div class="cell">
{updatedSymbols}
</div>
)
// this is magical trick
// [1,2,3,4,5].includes(props.number); //if props.number happens to be in the array then it i'll give true

Toggle 0 and 1 as boolean values in React

I'm making a toggle component in React and send the state to my database using LARAVEL.
When I'm sending the state of the toggle, in the database it's registered as 1 or 0, but when I'm activating/disabling the toggle, in the console.log it shows the values of true & false.
The problem here is that when I send the value to the database and I want to get it, the toggle doesn't recognize 0 and 1 because I'm writing a condition for if true or false, so I can't read the values registered on the db which are 0/1.
Is there a solution on how can I convert the received boolean to true/false ?
The hook and Handler :
const [showlogo, setshowlogo] = useState('');
const HideLogo = () => {
setshowlogo(!showlogo);
console.log(showlogo)
}
The toggle code :
<div onClick={HideLogo} >Toggle</div>
<div className={`${ showlogo ? "on" : "off" }`}>Valeur of logo</div>
If you want to toggle 0 and 1 as boolean values:
const { useState } = React
const response = {data: {showlogo: 0}}
function App() {
const [showlogo, setShowlogo] = useState(response.data.showlogo);
const hideLogo = () => {
setShowlogo(prev => prev === 0 ? 1 : 0); // <-- HERE
}
return (<div>
<div onClick={hideLogo} >Toggle (click), showlogo: {showlogo}</div>
<div className={showlogo===1?"on":"off"}> Valeur of logo</div>
</div>)
}
ReactDOM.render(<App />, document.body)
<script crossorigin src="https://unpkg.com/react#17/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom#17/umd/react-dom.production.min.js"></script>
Other answers recommended using Boolean, but since your db returns 1 or 0, and sounds like you have no control over it, then alternative use === operator
showLogo === 1 ? 'on' : 'off'
and use the following to toggle between 1 and 0
setShowLogo( showLogo === 1 ? 0 : 1 )
const status = 0
console.log(Boolean(status === 0))
console.log(Boolean(status === 1))
// IF it's a string then use String
const stringStatus = '0'
console.log(Boolean(stringStatus === '0'))
console.log(Boolean(stringStatus === '1'))
if you are dealing with 1 and 0 coming from the database, you can cast them to boolean with Boolean(x) -
Boolean(0) // false
Boolean(1) // true
and then if you have to save them again as 0 or 1, convert them back to a number from a boolean -
const x = showLogo ? 1 : 0
// then send x back to the db
Your initial value should be boolean
import React from "react";
let count = 1;
export default function App() {
const [showlogo, setshowlogo] = React.useState(0);
const HideLogo = (id) => {
if (id % 2 !== 0) setshowlogo(1);
else setshowlogo(0);
count++;
};
return (
<div>
<button onClick={() => HideLogo(count)}>Toggle</button>
{showlogo && (
<div className={`${showlogo ? "on" : "off"}`}>Valeur of logo</div>
)}
</div>
);
}
Demo
Just pass your id received from DB
onClick={() => HideLogo(ID)}
and toggle here based on passed ID
const HideLogo = (id) => {
if (id=== 0) setshowlogo(1);
else setshowlogo(0);
};

Conditionals in React

How do I use conditionals in React?
Essentially, for customerClassesRemaining, I currently say "class(es)" but I want to write code that says if there's one class, use "class," and if there's more than one class, use "classes." Thanks!
render() {
const loadBoxes = (
Array.from({ length: 20 }).map((n, i) => (
<LoadBox key={`${i}${n - 1}key`} />
))
);
const customerBoxes = !this.props.customersLessThanFive ? loadBoxes
: this.props.customersLessThanFive.map((customer, i) => (
if (customer.classes_remaining == 1) {
customerClassesRemaining2 = {`${customer.classes_remaining} class left`}
}
else {
customerClassesRemaining2 = {`${customer.classes_remaining} classes left`}
}
<CustomerFewerFiveBox
key={customer.id}
customerIndex={i + 1}
customerName={`${customer.firstName} ${customer.lastName}`}
customerClassesRemaining={`${customer.classes_remaining} class(es) left`}
customerPackage = {customer.name}
customerExpiration = {`Expiration: ${customer.expiration_date}`}
/>
))
you can try,
customerClassesRemaining2 = customer.classes_remaining == 1 ? `${customer.classes_remaining} class left` : `${customer.classes_remaining} classes left`;
Using ternary operators like:
customerClassesRemaining={`${customer.classes_remaining} class${customer.classes_remaining > 1 ? 'es' : ''} left`}

Categories

Resources