checkbox don't get first check in react - reactjs

I'm sorry I'm not that good at English and this is my first time to use this website. So My question might look a little bit strange.
I just wanna make a checkbox. When it got check signal, then I want to make it to express true, and when the checking is removed, then it should express false. But when I use console.log, I found that the first checking don't make any change and after checking is worked like toggle. I don't know why. My code is below, and in third picture, I just checked three time.
enter image description here
enter image description here
enter image description here

The setState function is async, so in the following lines of code inside your updateIsAgreeInfo the state isn't updated yet
You have to store the new value in a variable
Moreover, when setting a state based on old state value, you should use a function in setState instead of the raw value:
setIsAgreeInfo((oldValue) => !oldValue);

Change your updateIsAgreeInfo to this:-
const updateIsAgreeInfo = () =>{
setIsAgreeInfo(!isAgreeInfo);
console.log(isAgreeInfo)
signupPayload.isAgreeInfo = !isAgreeInfo;
}
or send event as a params in updateIsAgreeInfo and then access the current checked value of checkbox using event.target.checked. like:-
const updateIsAgreeInfo = () =>{
setIsAgreeInfo(event.target.checked);
console.log(event.target.checked)
signupPayload.isAgreeInfo = event.target.checked;
}

Related

useState doesn't run correctly in websocket connection

Hello guys I had a problem. I don't know it is a bug or not but I think it is a bug. I would open an issue on github repo of react but first I wanted to look at here and ask to you. I will give you all my code on the bottom of this post
What is the problem?
I am connection a socket when my component first mounted and catched the user to connect live chat. And I use useState to set messages when I or agent send a messsage on message event. I use useState on the line of 114. First of all this useState(setMessages on ) works correctly. But If I set the setMessages by the other ways this won't work.
For Example 1:
If I set this setMessages like below, setMessages works correctly and changes state but messages state not rendering on DOM correctly. I didn't udnerstand what's wrong.
const dummy = [...messages]
dummy.push(data.messageData)
setMessages(dummy)
For Example 2:
If I set this setMessages like below, setMessages doesn't work and I got an error and I never see my rendered page because it say ...prev is a null. I didn't understand what's wrong again.
setMessages((prev) => [...prev, data.messageData])
For Example 3:
This is the most interesting part of my code. It's really impossible one. If I remove line 111 and 112 (those are below here) the version of runs correctly of my codes doesn't work and setMessages doesnt work by the way with concat either. And I don't use those codes anywhere you can see that by using Ctrl+F. I just described those to set setMessages with the dummy variable but that didn't work and now I can't delete them because if I delete them my working codes won't work either.
const dummy = messages
dummy.push(data.messageData)
Now guys what's wrong on there. I fight all day with this buy I didnt find any reason. Is it a bug or not? Have a good days I will be here for your replies.
This is all of my codes in the page that I have a problem
https://gist.github.com/mucahidyazar/5ccff6d67d95d23dfb470dfe026f714b
You are using the useState incorrectly and its not a problem with react ;)
You need to create a new object reference if you use setState.
For example a string, number or boolean are always new instances.
But this does not work for objects. Push keeps the old object reference and setting a value to the same reference as before to the useState hook will be skipped.
const dummy = messages
dummy.push(data.messageData)
setMessages(dummy)
You are passing he same object to the setState (here setMessages) than before (push only adds the item to the same obejct), but you need a new instance instead, or else react will not rerender.
setMessages((prev) => [...prev, data.messageData])
but this only works if the default item is an array, so make sure you are setting ... = useState([]) so that prev is defined.
For line 111, yes the current object receives the new items, so the console.log shows the correct data,but since its the same instance (push does not create a new instance of the array), the rerender gets skipped and you will not see any changes on the resulting website.
o when I take a look at your code, change this:
const dummy = messages
dummy.push(data.messageData)
console.log(dummy)
setMessages(messages.concat(data.messageData).slice(0, messages.length)
to
setMessages([...messages, data.messageData])

Obtaining Selected Value in React-Select

I'm trying to implement this example that obtains the user selected value, but using the async select version.
I want to obtain the value that the user selected, but going through the docs on react-select this isn't clear how to do. If you set state equal to the inputValue, as soon as you click on the 'submit' button the inputValue is cleared. You get back
" "
instead of
user selected value
I'm not sure how to obtain the user selected value using the async select component. I have my API data successfully populating & filtering the suggestions box, but I can't figure out how to get the selected value.
I've tried numerous methods and lastly tried using the refs approach like in the above link, but the stored value shows up as null. Instead of storing the user selected value. Here is the link to my broken codesandbox.
Can anyone help or point me in the right direction?
Edit
Here is a link to a working demo if anyone gets stuck on this in the future.
So, what you got wrong is props of react-select to get value on on-change. Use onChange instead of onInputChange on your AsyncSelect Component. Both props are for different purpose. Here is a doc for all props available for react-select. https://react-select.com/props
Try code below
textChange = inputValue => { // whole object of selected option
this.setState({ inputValue:inputValue.value });
};
render(){
....
<AsyncSelect
defaultOptions
loadOptions={this.promiseOptions}
onChange={this.textChange} /** onChange triggers only when user change the
options but onInputChange triggers on each change which is for different
purpose like for e.g. when user type, fetch similar options **/
name="options"
/>
}

react-autosuggest with debounce and distinctUntilChanged

Intent:
I'm trying to achieve an ideal search field that will not make any API calls untill:
The debounce time of 350ms has been reached
AND until there's a change in the value of the input field.
What I've tried so far:
I've used a Subject to track for changes in the input field. Every time there's a change in the input field and handleSuggestionsFetchRequested is called, I'm pushing a new value down the Subject using searchString$.next(userInput);
And in the useEffect hook, I'm pipeing the searchString$ with debounceTime(350) and distinctUntilChanged(). Something like this:
useEffect(() => {
searchString$
.pipe(
debounceTime(350),
distinctUntilChanged(),
switchMap(searchString =>
ajax(`https://api.github.com/search/users?q=${searchString}`)
),
map((networkResponse: any) => networkResponse.response.items)
)
.subscribe((suggestions: Array<User>) => setSuggestions(suggestions));
}, [searchString$]);
But the API calls are still going everytime there's a change in the userInput.
The Issue:
I think the issue is that every time the value of the input field changes, I'm setting the state as well:
const handleChange = (
event: React.ChangeEvent<{}>,
{ newValue }: Autosuggest.ChangeEvent
) => {
setUserInput(newValue);
};
This is causing the Component to re-render and calling the useEffect, which is eventually making the API call again and again.
I could be wrong.
How to replicate:
I've created a Sample Code Sandbox that replicates the issue.
Thanks a lot in advance.
Thanks to the comments from yurzui on my tweet, I was able to figure out the reason for the issue.
I was creating a new Subject on every reconciliation as the line:
const searchString$: Subject<string> = new Subject<string>();
was right inside my component function.
I moved it out and it was working like a charm.
NOTE: As suggested by yurzui, don't forget to catch errors in the ajax call otherwise the Subject will die.
I've updated the Code Sandbox Sample, just in case somebody needs to refer to it.

Whether it is good to do lot of functionality in the setState Callback?

I am trying to check and uncheck a checkbox based on other conditions in screen..
I am printing an element using document.getElementById('foo') this is returning null even my element is present in screen and in DOM.
Please help me to solve problem.
I am developing code in which after API is being fetched state variable need to be set and do other functionality based on the respective state variable.
Is it feasible to do most of the logic inside the call back of the setState to promote synchronus way of coding or any other concepts are present to do the same?
this.setState({
filter:filterValue
},function(){
// Most of the coding logic goes here
})
Please suggest a prominent way if it is wrong
Well you definitely shouldn't use document.getElementById since it's against reactive programming logic but it's hard to say where is a problem if you don't provide example code.
Try to implement checkbox in React way:
const CheckBoxComponent = (isChecked) => {
return <CheckBox checked={isChecked ? true : false}/>
}
then in your return:
<CheckBoxComponent isChecked={yourFunctionWhereYouResolveWheneverIsOrNotChecked}/>
Another point is that you really won't to hold logic in setState callback. I guess you are a beginner. You should get better knowledge of functional programming. It's easier than handling state logic and mutation.
Judjing from your question you want probably something like that:
const yourAsyncCallToApi = async() => {
await someApiCall()
yourFunctionWhereYouResolveWheneverIsOrNotChecked() //it will be called as soon as u got data from api call
}
const yourFunctionWhereYouResolveWheneverIsOrNotChecked = () => {
// handle your conditions and return false or true based on them
}

Is there a better way of updating the tx hash?

Following is a snippet of my code (which is working)
....
let txhash = '';
class App extends Component {
....
async componentDidMount() {
.....
}
onSubmit = async(event) => {
event.preventDefault();
const accounts = await web3.eth.getAccounts();
this.setState({
message: "Waiting for the transaction to be mined..."
});
await lottery.methods.enterLotteryContract().send({
from: accounts[0],
value: web3.utils.toWei(this.state.value, 'ether')
}).on('transactionHash', function(hash) {
txhash = hash
});
this.setState({
message: "Congrats, the tx has been mined; your txhash is " + txhash
})
console.log(txhash);
});
}
More over here: https://github.com/DKSukhani/lottery-react/blob/master/src/App.js
Was wondering if there is a better way for me to get the txhash and then display it. I was hoping that I could make txhash as one of the state components rather than declaring it as an empty variable. Also I am using the call back function in only reassigning it to txhash.
Can you ask your question a bit more clearly? Your code makes sense and looks fine for some unknown purpose. That purpose is exactly what I need to know though.
When do you need the txHash, is it after every call of this function or are you trying to track something else.
Why can't it be a state variable, you didn't include state in your snipped so I had to go look at the rest of your code and see no reason why not. You use it within the snippet so it's clear you can use it to some degree. I don't use React so maybe there's some render loop, listener issue, or other reason you can't use setState.
With that said, check out this link on the different events you can listen to with on, as I think you're listening to the wrong event or outputting the wrong text. When you set the state's message to say that the tx was mined I don't believe it actually has been.
I would use confirmation and only display the message on the first fire of the event, then ignore the remaining 23. The object returned alongside the confirmation number is described here and has a transactionHash variable you can use to both check that the transaction was confirmed and get the hash at the same time. Now your event call is no longer as wasteful and you can use the same setState call for the message as for the txHash, or even skip storing the txHash at all (as long as you can still use setState asynchronously).

Resources