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);
};
Related
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>
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
I have a counter / calculator app which takes the count value from multiple instances of a Counter component and combines them as the final result. The Counter component has an increment and a decrement button that add or subtract the count value in each instance. The value cannot be negative.
The problem I'm having is that the value is supposed to show as a double digit, meaning that the starting value is 00 and increments as 01, 02 until it reaches 10. My solution was to use a string literal to show a 0 in front of the value as long as the value is less than 10, but this is causing problems with my handleValue logic, and now the decrement button no longer responds.
Everything worked as it should before adding the string literal.
I cannot seem to figure out why the string literal is causing these problems or how to fix them. Any help would be greatly appreciated!
Code:
const Calculator = ({ onClick }) => {
const [values, setValues] = useState({
count1: 0,
count2: 0,
count3: 0,
});
const handleValue = (key, value) => {
if (!((values.count1 === 0) && (value === -1))) {
if (!((values.count2 === 0) && (value === -1))) {
if (!((values.count3 === 0) && (value === -1))) {
setValues((prevState) => ({ ...prevState, [key]: prevState[key] + value }));
}
}
}
};
return (
<div>
<Counter
id="count1"
value={values.count1 < 10 ? `0${values.count1}` : values.count1}
handleValue={handleValue}
/>
<Counter
id="count2"
value={values.count2 < 10 ? `0${values.count2}` : values.count2}
handleValue={handleValue}
/>
<Counter
id="count3"
value={values.count3 < 10 ? `0${values.count3}` : values.count3}
handleValue={handleValue}
/>
<button
type="button"
onClick={onClick}
>
SHOW RESULT
</button>
</div>
);
};
export default Calculator;
<Counter
id="count1"
value={values.count1 < 10 ? `0${values.count1}` : values.count1}
handleValue={handleValue}
/>
Here the type of value prop in Counter component isn't number. If you want to do some caculation, you'd better keep the type as number something like below
<Counter
id="count1"
value={values.count1}
handleValue={handleValue}
/>
So here what you need is to show the number starting with "0" if it is less than 10. In this case you can just make some trick on the visual side of the component.
Actually, I am not sure where you are showing value (maybe in Counter component?), but that's where you should use string iteral.
I am writing a program that uses checkboxes to filter a list of items.
I have a group of 3 checkboxes: phase, specialty, and type. Once the checkboxes are marked, they are put into an array which is then used to filter out a list if the conditions match.
When making this, I ran into a few issues:
If no boxes were checked, then no list would appear at all.
If a box in all categories were checked, then it would show both conditions rather than when both are true (so if I had phase Base 1 and specialty Race checked, then the list would show all Race matches and all Base 1 matches)
If a box was not checked but another one was, then nothing would appear since it didn't fit both categories.
To fix all three of these issues, I made an if, if/else statement to check the array length of each category. If all arrays (checkboxes) were empty (unchecked), then the original list would appear. If 1 box was checked, but the others weren't, then nothing would break. Etc.. This was made into quite a long statement.
Now, I do plan to add 2-3 more checkbox options, and don't want to complicate things even more. If I keep doing the way that I'm doing now, I may end up with double the current statements I have now.
Currently, the way this list is being filtered is the following, note, the console.logs are to recognize which condition I am using:
if (phases.length === 0 && specialties.length === 0 && type.length === 0) {
const workouts = this.workouts;
this.selectedWorkouts.next(workouts);
} else if (phases.length > 0 && specialties.length > 0 && type.length > 0) {
const workouts = this.workouts.filter(
workout => byPhase(workout) && bySpecialty(workout) && byType(workout)
);
this.selectedWorkouts.next(workouts);
console.log("1 EVERYTHING CHECKED");
} else if (
phases.length > 0 &&
specialties.length > 0 &&
type.length === 0
) {
const workouts = this.workouts.filter(
workout => byPhase(workout) && bySpecialty(workout)
);
this.selectedWorkouts.next(workouts);
console.log("2 PHASE AND SPECIALTY (no type)");
} else if (
phases.length > 0 &&
specialties.length === 0 &&
type.length > 0
) {
const workouts = this.workouts.filter(
workout => byPhase(workout) && byType(workout)
);
this.selectedWorkouts.next(workouts);
console.log("3 PHASE AND TYPE (no specialty)");
} else if (
phases.length > 0 &&
specialties.length === 0 &&
type.length === 0
) {
const workouts = this.workouts.filter(workout => byPhase(workout));
this.selectedWorkouts.next(workouts);
console.log("4 PHASE ONLY (no type or specialty)");
} else if (
phases.length === 0 &&
specialties.length > 0 &&
type.length > 0
) {
const workouts = this.workouts.filter(
workout => bySpecialty(workout) && byType(workout)
);
this.selectedWorkouts.next(workouts);
console.log("5 SPECIALTY AND TYPE (no phase)");
} else if (
phases.length === 0 &&
specialties.length > 0 &&
type.length === 0
) {
const workouts = this.workouts.filter(workout => bySpecialty(workout));
this.selectedWorkouts.next(workouts);
console.log("6 SPECIALTY ONLY (no phase nor type)");
} else if (
phases.length === 0 &&
specialties.length === 0 &&
type.length > 0
) {
const workouts = this.workouts.filter(workout => byType(workout));
this.selectedWorkouts.next(workouts);
console.log("7 TYPE ONLY (no phase nor specialty)");
}
Is there a way to refactor this so I don't continue to add on to the statements, making it an even longer block of code? Or is this not really much of a concern to keep my statement so long?
Here is the stackblitz to my full project. You can find the if/else statements in src/app/features/workouts-page/workoutservice/workout.service.ts. The code is found above should be specific enough for this statement.
Thank you.
Here's how I would do it. This uses a single filter pass:
filterWorkouts(phases: string[], specialties: string[], types: string[]) {
const workouts = this.workouts.filter(workout => {
return (
(phases.length === 0 || phases.indexOf(workout.phase) >= 0) &&
(specialties.length === 0 || specialties.indexOf(workout.specialty) >= 0) &&
(types.length === 0 || types.indexOf(workout.type) >= 0)
);
});
this.selectedWorkouts.next(workouts);
}
You would need to add a one-liner for each additional filter is all. Here's a working implementation on stackblitz for you to play around with.
Since the byPhase and related functions are just functions, you could store them in an array based on the values. Then you could call the functions within the array to pass up to your filter.
function byPhase(workout) { console.log('by phase'); }
function bySpecialty(workout) { console.log('by specialty'); }
function byType(workout) { console.log('by type'); }
// This should filter without specialties
phases = [1,2,3];
specialties = [];
type = [3,4];
const workoutFilters = [
phases.length > 0 ? byPhase : null,
specialties.length > 0 ? bySpecialty : null,
type.length > 0 ? byType: null,
].filter(Boolean);
// Show selected filters
console.log('filters:', workoutFilters);
You can always return from your if to avoid using an else if as long as there isn't something afterwards. In your case, there wasn't so that's one way to shorten things up.
Also, len === 0 can always be replaced with !len as it's a bit more succinct and instead of len > 0 it can just be if (len) if you're comfortable with that, some don't find it as read-able so I'll leave it up to you.
I noticed the same line came after filter op: this.selectedWorkouts.next(workouts); so I moved that to the end and only wrote it once outside of the other blocks to avoid having it run at the end of each block.
Then I noticed that you are basically just trying to use that filter if one of the filters is applied so instead of else if, I used 3 if statements that will apply the filtered param and moved workouts up in scope and gave it its own unique variable so instead of filtering on this.workouts you are filtering on the wo in the fn and updating it each time. This way, you don't have to check for the negative conditions as it won't filter them if the condition doesn't apply and will filter again if a second param applies (gives you the && without writing out every condition).
I think this is a very read-able solution that mostly preserves the code you've written so far.
filterWorkouts(phases: string[], specialties: string[], type: string[]) {
const byPhase = workout => phases.some(phase => workout.phase === phase);
const bySpecialty = workout =>
specialties.some(specialty => workout.specialty === specialty);
const byType = workout => type.some(type => workout.type === type);
let wo = this.workouts;
if (phases.length) {
wo = wo.filter(workout => byPhase(workout));
console.log("CHECKED PHASE");
}
if (specialties.length) {
wo = wo.filter(workout => bySpecialty(workout));
console.log("CHECKED SPECIALTY");
}
if (type.length) {
wo = wo.filter(workout => byType(workout));
console.log("CHECKED TYPE");
}
this.selectedWorkouts.next(wo);
return;
}
}
I want to save the checkbox value as "Yes" / "No" instead of "true" / "false" in database. Am using reactjs to fetching the values and storing in the database.
Please find my below code, that am trying.
handleInputChange(e) {
const target = e.target;
const name = target.name;
const item = this.state.item;
const value = target.type === 'checkbox' ? target.checked : target.value;
if( name === "should_create" && value === false )
{
this.state.item.should_create="No";
}
else if( name === "should_create" && value === true )
{
this.state.item.should_create=="Yes";
}
else
{
this.state.item.should_create=="";
}
item[name] = value;
this.setState({ item: item });
}
HTML Check box code :
<input name="should_create" checked={this.state.item.should_create==true ? "true":''} type="checkbox" value={ this.state.item.should_create } onChange={ this.handleInputChange } />
But, the above code is not working properly. Its storing the default value "true" / "false" only. How can i change it to "Yes" / "No" value ?
I have multiple "Checkbox" component, but i want this "Yes" / "No" options for this only one component. Remaining component should be as default.
You use == as an assignment, but it's almost the same as === (an expression that returns true or false)
So it's better to create a variable and then just update the state
let shouldCreate = ''
if (name === 'should_create') {
shouldCreate = value ? 'Yes' : 'No'
}
item[name] = value;
this.setState({ item: item });
Likely it should help https://codesandbox.io/s/v8v267m23l