React-Redux Slider undefined value when passing onwards the values - javascript

This is my first post so I'm sorry if I'm doing it wrong. So, I've started creating a webpage for my portfolio with React and Redux but I hit a point where I can't find the solution or the flaw in my logic. The page is that the user can select a skill and then the pointer to the value he knows. I can save the skills to localStorage but I can't manage to pass the skill value from the slider to save it. If anyone can help with any tip or info of where I m doing wrong please help.
This are some of the components:
slider component
skillsComp whee the slider is passed
listSkills Comp where skillsComp and Slider is passed
redux actions
redux reducer
and this is the console output: console

Problem: Not Dispatching Action
The problems that I'm seeing are in image #1 of the SkillSliderBar component. There might be other issue too, I haven't looked further then this.
First of all, your destructured props are missing the addSkillValue function from mapDispatchToProps.
You defined a function handleChange to call the addSkillValue function, but you never call handleChange. Instead you are calling changeValue which updates the local component state.
You probably don't need a local state at all. You can use the skillValue from mapStateToProps as the value for your inputs. To set the value, call addSkillValue from mapDispatchToProps.
Make sure that the onChange function for your inputs is being called with the value first and not the event. If it is being called with the event then your handleChange would look like:
const handleChange = e => {
addSkillValue(e.target.value);
}
Suggestions: State Shape
It looks like you only have a skill value in your state for the current skill. Probably what you want is to store an array of skill objects with properties name and value. Or possibly a key-value object where the keys are the skill names and the values are the skill values. I'm not sure if you need the currentSkillName. You can update the value for any skill by dispatching an action that contains both the new value and the name of the skill that you are updating.

Related

Issue with update timing for a state in React Component (2 clicks needed instead of 1)

I’m working on a solo project using React and I’ve been stuck on something for the past 2 days…I'm starting and I'm very beginner so it's maybe something very basic, but I'm struggling...
To try to be concise and clear:
I have a searchBar component, that searches through a local database, and returns objects associated with the search keyword. Nothing complicated so far.
Each rendered object has a button that triggers a function onClick. The said function is defined in my App component and is as follow:
changeState(term){
let idToRender=[];
this.state.dealersDb.map(dealer=>{
if(term===dealer.id){
idToRender=[dealer];
}});
let recoToFind=idToRender[0].reco;
recoToFind.map(item=>{
Discogs.search(item).then(response=>{idToRender[0].recoInfo.push(response)})
})
this.setState({
objectToRender: idToRender
});
to explain the above code, what it does is that first, it identifies which object’s button has been clicked on, and send said object to a variable called idToRender. Then, it takes the reco state of that object, and store it to another variable called recoToFind. Then it calls the map() method on recoToFind, make an API request (the discogs() method) for each element of the recoToFind array and push() the results into the recoInfo state of idToRender. So by the end of the function, idToRender is supposed to look like this:
[{
…
…
recoInfo: [{1stAPI call result},{2ndAPI call result}…]
}],
The array contains 1 object having all the states of the object that was originally clicked on, plus a state recoInfo equal to an array made of the results of the several API calls.
Finally, it updates the component’s state objectToRender to idToRender.
And here my problem is, onClick, I do get all the states values of the clicked on object that get rendered on screen (as expected with how I coded the nested components), BUT, the values of the recoInfo are not displayed as expected (The component who’s supposed to render those values is nested in the component rendering the clicked on object other states values). However, they get displayed properly after a SECOND click on the button. So it seems my problem boils down to an state update timing trouble, but I’m puzzled, because this function is calling setState once and I know for a fact that the state is updated because when I click on the button, the clicked on Object details get displayed, but somehow only the recoInfo state seems to not be available yet, but only becomes available on a second click…
Would anyone have a way to solve this issue? :(
It somehow feels like my salvation lies in async/await, but I’m not sure I understand them correctly…
thanks very much in advance for any help!
Is this someting you want to do?
changeState(term) {
let idToRender=[];
this.state.dealersDb.map(dealer=>{
if(term===dealer.id){
idToRender=[dealer];
}});
let recoToFind=idToRender[0].reco;
recoToFind.map(item=>{
Discogs.search(item).then(response=>{
idToRender[0].recoInfo.push(response)
this.setState({
objectToRender: idToRender
});
})
})
}
you can call setState once async call is done and result received.

How does useState update our state?

This is a very detailed question but im wondering...
let [state, updateState] = useState()
that piece of code returns an initial state, but when we use updateState, how does react actually go into our code and change that "state" ,which is an already updated value? How do they have access to our code to change it like that?
Initial state is stored in [useState("INITIAL-STATE_VALUE")]. and This statement takes toe parameter's first one is the name of state and the second one is the function which update the state when you call it.
So whenever you called that function that will update your state according to you..

How to show Toast only once after received error message prop from Redux store

I have working React-Native + Redux registration flow:
Fill inputs
Validate them in component (Formik)
Call action to store registerUser(formData)
Wait for saga to do async call to API
On API error call reducer REGISTER_ERROR what sets store variable formError to some message.
I have my component with mapped state to props (this error message is hooked to prop).
I am doing componentDidUpdate() and when the error prop from store is changed I fire ToastAndroid.show(errorMessage).
But my Toast is called multiple times, because componentDidUpdate is also called multiple times (Redux updating component multiple times).
I know quick workaround by for example creating local state visible and when this state variable is true then no other Toasts are shown.
Is there any better more common way to do it? It is pretty weird in my opinion to rely on Toast's onClose event to set the state variable to false.
As stated in the first answer it'd be good to see the actual code, but what you should be doing is only showing the toast message when the prop changes like this (assuming it's a boolean)
componentDidUpdate(prevProps) {
if(prevProps.showToast === false && this.props.showToast === true){
showToast();
}
}
Without the code, it's a bit hard to try coming up with a solution but I think I know at a high-level what you are trying to do.
If I were you, I would make the presentational component (toast UI in this context) just react to the store props/observables instead of calling the ToastAndroid.show() method directly in the life cycle method.
In terms of architecture pattern, I find this pattern works well with react applications. Hope this helps. https://medium.com/#dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0

Multiple input fields painted via loop not updating new values on insertion in react and redux

I am working in React with Redux.Things looked very free flowing untill I came across one problem.May be I am not implementing this particular part the right way.However I need your help in this.
So I have a react component and on componentWillMount() I get data from an API call
I have my actions and action creators in place such that it dispatches a getSupplier action,I store them in redux state as supplierList which is an array of objects like
[{name:'Bob',score:10,id:1},{name:'John',score:10,id:2}];
Now My UI comprises of a table with name and score as table data.Score will be an input field which will initially have score values which came from the getSupplier service.
I have looped and returned the jsx inside my component as follow
render(){
var data = this.props.supplierList;
if(data.length){
return (
<div className='fx-container'>
{
data.map((v,i)=>{
(<div class='fx-table-row' key={v.id}>
<div class='fx-supp-name'>{v.name}</div>
<input
type='text'
className='fx-input'
value={v.score}
onChange={(e)=>{this.handleInputChange(e.target.value)}}
onBlur={(e)=> {this.props.actions.updateScore(v.id,e.target.value)}}
</div>);
});
}
<div>
);
}
else{
return null;
}
}
So I am painting my intial values and on inserting of new value and on blur I need to update the new value by dispatching an action which is written in action.js file
The probblem I am facing is that I am not able to insert any value into the input.I am not able to hit backspace and insert new values.
Kindly help as I am new to react and redux.
PS: Above code is a dummy code just to illustrate my problem.
First, you might not want to call an API in componentWillMount. See this post: https://daveceddia.com/where-fetch-data-componentwillmount-vs-componentdidmount/
The reason you're not able to modify your input is that this is a controlled field and you're not calling an onChange event. See https://facebook.github.io/react/docs/forms.html
It's because of value={v.score}
The value of Input field is controlled by v.score and it is from props
So in the this.props.actions.updateScore() function you should change the score so that the props change.
The value of Input field will never change unless the props are changed
Also you should use onChange() instead of onBlur()

Is this a React bad practice?

So, I'm trying to learn some react, so far egghead.io is pretty good, but I have a question. I have the following code:
https://jsfiddle.net/42pe/69z2wepo/49393/
Basically these are 3 sliders which update the state on the parent component. Pretty straightforward.
Specifically, I can update the state like this (by passing both val and color):
updateMe(val, color) {
let obj = {};
obj[color] = val;
this.setState(obj);
}
Or I could use the Slider ref to findDOMNode() and then get the value to update the state, but that just didn't feel right. I have no clue what React does in the back, but calling a function from an instance, just so that function can find the instance again to get it's value, when the instance itself could be passing it's value (both value and color prop) all along seems weird.
So, is this a bad practice for some reason?
Both methods are correct but prefer the updateMe . Passing functions in props and child calling that prop function is the ideal way in React.
Refs are ideal where you just want the value and dont want to update state of the react component .For eg , in forms you can use ref to get all the values and make a ajax call to the server.
A better and much cleaner way to do this using ES6 is:
updateMe(val, color) {
this.setState({
[color]: val
});
}
findDOMNode is not a bad practice. But you do not need use it if, you build your application as a function of state and props.
Any change to your state or props should change your DOM and any change to your DOM should be as a result of function of change in state or props.

Categories

Resources