How would I change the component props onClick with a functional component? - reactjs

I am trying to change the value of the prop onClick. Basically the model is set up to show only one input bar if the enum is set to one and vise versa for two. How would I switch the value of the prop with an onClick function? Below is what I have tried to this point. Right now I am getting the following error: "Argument of type 'boolean' is not assignable to parameter of type 'SetStateAction<Enum_Search_Inputs | null | undefined>'"
const [pickInput, setPickInput] = useState(search.inputs)
<Breadcrumb
borderBottom={'1px'}
borderColor={'white'}
color={'white'}
separator=""
>
<BreadcrumbItem>
<Button color={'white'} variant='link' onClick={() => setPickInput(pickInput === 'two')}>Search by location</Button>
</BreadcrumbItem>
<BreadcrumbItem>
<Button color={'white'} variant='link' onClick={() => setPickInput(pickInput === 'one')} >Search by keyword</Button>
</BreadcrumbItem>
</Breadcrumb>

You should add boolean type when you declare pickInput
const [pickInput, setPickInput] = useState<Enum_Search_Inputs | null | undefined | boolean>(search.inputs)

It looks like you're trying to set the state as a boolean instead of as a one or a two. Your function should look like the one below if you're trying to set the state to be the word "one" or "two", though I'd definitely recommend using an integer for that.
() => setPickInput("one")}
() => setPickInput("two")}
Right now, you're actually doing a comparison inside the function where you set your state (pickInput === 'one') which is going to return a boolean to your setPickInput function based on whether your variable pickInput's value is 'one' instead of actually setting a value inside it.
React Docs link to hooks and state
JS Comparisons documentation

I was able to solve this by setting up a function that used state to set the value on click.
function searchLocationHandler() {
setPickInput('two')
search.inputs = 'two'
}
function searchKeywordHandler() {
setPickInput('one')
search.inputs = 'one'
}

Related

How to get value of data custom-attribute in JSX / React

Let's say I create a data-custom attribute in JSX element to save some meta-data about that element.
Like:
return (
<button data-customData="red" onClick={(ev) => { console.log(ev.target.customData)}}>Teste</button>
)
If I try to acess the data-custom attribute like you see in the code I will get undefined.
But If I try something like ev.target.style or ev.target.id I will not get undefined.
What is the difference and how can we acess this value ?
you're not calling the right value, you are calling a property called customData but the attribute name is data-customData, and in order to get the value you need to change how you call the attribute using the getAttribute function that the element (ev.target) provides
return (
<button
data-customData="red"
onClick={(ev) => {
const element = ev.target;
console.log(element.getAttribute("data-customData"));
}}
>
Click Me
</button>
)
The thing you're trying to is not a very common pattern and if you want to get a value from the user you should use the right control (input, radio, select) instead of using a data attribute.

Event.target types for name input in FromHandler with TypeScript

I have a simple form in a React SPA with typescript.
I'm going to make this form processing simple, without adding component state and so, just to get value from the named input, name = 'gameId'.
There are two ways I've tried in the example below:
If I use event.target, TS says the "children" doesn't exist on type 'EventTarget'
If I use event.currentTarget, TS says the "gameId" doesn't exist on type 'HTMLCollection'.
Is there any way to solve these?
const submitAcceptGameHandler: React.FormEventHandler<HTMLFormElement> = async (event) => {
event.preventDefault();
// 1st
// Property 'children' does not exist on type 'EventTarget'.ts(2339)
const inputData = event.target.children.gameId.value;
// 2nd
// Property 'gameId' does not exist on type 'HTMLCollection'.ts(2339)
const inputData = event.currentTarget.children.gameId.value;
console.log(inputData);
};
<form onSubmit={submitAcceptGameHandler}>
<button type="submit">ACCEPT GAME</button>
<input name="gameId" type="text" placeholder={'Input game id...'}></input>
</form>
The issue with the event.target.children
children is an HTMLCollection, similar to an array. You can get values by its index children[0] or chilren[1]
Either you need to go over all your children or convert it to an array and find the desired component by its name or id
To convert you can just use the spread operator
const children = [...event.target.children]
const gameId = children.find(child => child.name === "gameId")?.value
ANYWAY
I would highly recommend having control over your fields and always having state management for them.
You can even use some libraries to manage your forms.
I prefer using react-hook-form, but you can choose anything you want

handle checkbox data and store in a state/variable

How can I store the selected value in another state and stop unchecking the value when I select another button?
const Notifications = () => {
data:[
{id:1, name:apple, notification:{id:1,msg:"hi"}, {id=2,msg:"hlo"}},
{id:2, name:banana, notification:{id:13,msg:"hi"}, {id=3,msg:"hlo"}}
{id:3 ,name:mango, notification:{id:14,msg:"hi"}, {id=34,msg:"hlo"}},
{id:4, name:grape, notification:{id:15,msg:"hi"}, {id=341,msg:"hlo"}},
{id:5, name:carrot, notification:{id:16,msg:"hi"}, {id=4,msg:"hlo"}},
]
const onCheckedValue = (e) => {
const { checked, value } = e.target;
if (checked) {
setCheckedData([...checkedData, value]);
} else {
setCheckedData(checkedData.filter((item) => item !== value));
}
};
return(
<>
{data.map(d => {
<Button onClick=(setActive(true))>
{d.name}
</Button>
})}
//render the notifications when I clicked on the button I want to store the checked value in a state with respect to the selected button and checked notification.
{active ?
data.notifications.map((notification) => (
<div className="checkbox">
<Checkbox
onChange={onCheckedValue}
value={notification}
/>
/div>
}
</>
)
}
You can use the React Use State Hook. You'll want to define a variable and a state setter for that variable like so:
const [selected, setSelected] = useState([]);
Then when you click or un-click a checkbox, you can call setSelected with the updated selected value. I instantiated selected as an empty array in my example, so you'd arr.push(new value).
Your second block of code is where there are issues.
You are attempting to access properties on data, but that is an array and you cannot access the properties of the objects inside of it like that.
You will need to loop over the array or access an index of the array directly in order to access notifications.
As a side note, you are attempting to use the ternary operator to conditionally render (?), but not supplying the second argument after the :. I gave it a value of null so that it doesn't render anything if not active.
That could look something like this:
// I don't know where active comes from, but I'll assume that's correct.
{active ? (
data.map((item) => (
<div className="checkbox">
<Checkbox
onChange={onCheckedValue}
checked={!!checkedData.find(name => name === item.name)}
value={item.name}
/>
</div>
))) : null
}
In this example, I map over data and create a Checkbox for each item in the array. I don't know if that's what you want as it's unclear. However, with your onCheckedValue function, it will make updates to the checkedData array.
You should pass the prop checked to control the checkbox's state. I set the checked value to the return of checkedData.find(), and used the double-bang (!!) operator to coerce it into a Boolean value (true or false).
The find operation will be looking to see if the data[i].name matches any value in the checkedData array, since you are storing the object's name property in the checkedData array. If it finds nothing, it will be !!undefined which will evaluate to false, and if it does find it, it will be !!"banana" which evaluates to true.

React button type changed while passing in a value

So Im working on React with flowtype, and I have a value with a type of say ItemType, and it is an object of different properties.
For example, if I declare item: ItemType, and in console log item will print out
Item { Property1: 'someValue', Property2: 'someValue', Property3: 'someValue'}
I am trying to pass in the variable as a value, such as
<button value={item} onClick={this.onButtonClick}>Click Me!</button>
Supposedly the item I passed into the value is an ItemType, but when I checked the type it becames a string. I tried console logging the type inside the callback function as below
onButtonClick = event => {
console.log("type checking: " + typeof event.target.value); // Output: type checking: string
}
I don't know why this is happening as I need the variable to be the correct type instead of string. Can anyone explain this issue?
The buttons value attribute is associated with its name when submitting a HTML form, have a read of the prop here:
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button
To achieve what I believe you want you can try this:
<button onClick={() => this.onButtonClick(item)}>Click Me!</button>
You should then have access to the item object inside the onButtonClick method.
onButtonClick = item => {
console.log(item)
// output: { Property1: 'someValue', Property2: 'someValue', Property3: 'someValue'}
}

How to pass a function instead of string as a prop to a component

I'm really new to reactjs and I was looking for a simple way to change the color of a button depending on states. Basically I'm using reactstrap and I have a button, I want its color to be "secondary", "danger" or "primary" the Button tag works that way :
<Button color={String} />
I want to use a function to put a String in there. basically here is a small function :
buttonClassName(radioId) {
if (this.state.whatevs.valid === false)
return "danger";
if (this.state.whatevs.value === radioId)
return "primary";
return "secondary;
}
here is how I want to use it :
<Button outline color={() => this.buttonClassName(1)}>blah blah1</Button>
<Button outline color={() => this.buttonClassName(2)}>blah blah2</Button>
<Button outline color={() => this.buttonClassName(3)}>blah blah3</Button>
and so on for more buttons, problem is, react logically barks at me because :
Warning: Failed prop type: Invalid prop `color` of type `function` supplied to `Button`, expected `string`.
I agree with it, but how can I make that string change without passing a function, do I have to make state out of it, it seems so boringly circumvoluted. When I only had two states, I could just do something like that :
<Button outline color={(whatevs.valid === false)?"danger":"secondary"}>blah blah1</Button>
and that's not really a string either, but it worked.
You can most definetly use a function to return a string. The problem with your implementation is that you were passing a whole function by reference rather than the result of a function.
Just do this simple fix below. This will execute the function and return the desired string to the <Button> component.
<Button outline color={this.buttonClassName(1)}>blah blah1</Button>
<Button outline color={this.buttonClassName(2)}>blah blah2</Button>
<Button outline color={this.buttonClassName(3)}>blah blah3</Button>

Resources