On a button, I have a onClick handler
const handleSelectOpen = (noteId) => {
let newState = {notes: state.notes, noteDetailScreen: true, activeNote: noteId, newNoteScreen: false, newNoteText: "", newNoteRelated: []};
setState(newState);
};
Which does two important things, it sets noteDetailScreen in the state to true, causing the MUI Dialog to appear. It also sets activeNote to noteId, which is the content that should be displayed in the dialog.
That content is then displayed with {state.notes[state.activeNote].content} inside the dialog. The issue being most of the time, its displaying the wrong content! noteId is always correct, but the state is not always correct. How can I fix this>
when updating state based on the previous state, you should pass an updater function to setState. It takes the pending state and calculates the next state from it.
setState(prev => ({notes: prev.notes, noteDetailScreen: true, activeNote: noteId, newNoteScreen: false, newNoteText: "", newNoteRelated: []}))
Related
This is a Framer/React question:
I have a bunch of text fields in a "page" component and I want the focus to shift on every "page" change.
There's a button controlling the pager but no trigger (onPageChange / onClick) is changing the attribute of "focus" on the relevant text input.
This is the code I tried using to change the value of foc2 (the focus attribute) to true
When I manually change it to true it works, but in this case it doesn't
export function Page(): Override {
return {
currentPage: state.page,
onChangePage: (index) => {
state.page = index
state.foc2 = true
},
}
}
Do you have more complete code you could share?
Make sure you set the state to the index of the current focused input, and use that to change the currentPage property.
Happy to help if you send more context, you can also find more help in Framer's community at https://framer.com/r/discord
I am saving the form data in react to redux store and every input works fine except the checkbox. The problem is that checkbox never shows tick mark but redux-logger shows that the state of the checkbox has been changed in the state. Below is my checkbox
<Control.checkbox model="agree" name="agree"
className="form-check-input"
changeAction={this.changeAction} defaultChecked={this.props.fields.agree}
updateOn="toggle"
/> {' '}
<strong>May we contact you?</strong>
this.props.fields.agree gives the current status of the checkbox tken from redux store.
Below is the reducer:
const InitialFeedback={
firstname: 'Vipul',
lastname: 'Tyagi',
telnum: '12345',
email: 'vipultyagi629#gmail.com',
agree: true,
contactType: 'Email',
message: 'Hello'
};
export const formsData=(state=InitialFeedback,action)=>{
switch(action.type){
case 'CHANGE_FIELD':
return {...state, [action.payload.name]: action.payload.value};
default:
return state
}
}
Below is the changeAction method:
changeAction(model, value){
console.log(typeof(value));
this.props.dispatch({type:'CHANGE_FIELD',payload:{name: model, value: value}});
}
The checkbox indeed respond to tick but doesn't shows tick mark. What mistake I am doing?
Please help me to find the problem!!
EDIT
I have just checked that whatever the initial state of checkbox is, it always remains same. I mean if initially in store I set agree to true then the checkbox starts showing tick mark, but on clicking on the checkbox, the tick mark doesn't goes off. Similar is the for the case when initial state is false.
As title says, I set up a checkbox which has the issue that I need to click on it twice to change it's state
The first time I click it behaves as expected, but every attempt after that requires double clicking.
state = {
notification: true,
};
handleInputChange= (event) => {
//I use event.target to operate since I'm trying to set up multiple checkboxes
this.setState({ [event.target.id]: !event.target.checked });
};
<AppSwitch
checked={this.state.notification}
onChange={this.handleInputChange}
className={"mx-1 switch-color"}
color={"success"}
variant={"pill"}
id="notification"
name="notification"
/>
You don't need to ! when you're setting state here. It should be this.setState({ [event.target.id]: event.target.checked });, since event.target.checked returns the checked state of the checkbox. So, if you click the checkbox and it transitions to checked, then it will be true. Then, if you click the checkbox and it transitions to unchecked then it will be false.
I'm trying to update the state of the id value in shoeList. Currently I have a textfield that allows for entering of a new ID and I want the state to update when the OK button is clicked.
Here is some of the relevant code:
state = {
editingToggle: false,
shoeList : [
{name: 'bob', id: '123213-0', shoeSize: 'L'}
],
}
<TextInput className='text-area-header' id="textM" width="m" type="text" placeholder={this.state.shoeList[0].id} />
<Button className="ok-button" variant="tertiary" size ='xs' type="button" handleClick={this.saveHeader}>OK</Button>
saveHeader(e) {
this.setState(state=> ({
shoeList[0].name:
}))
alert('Header changed to ' + this.state.shoeList[0].id);
e.preventDefault();
}
I'm not sure what to put in this.setState as I haven't found anything on how to update nested values through a google search. Also whenever I put a value attribute to the TextInput tags it doesn't allow me to edit in the textinput on the webpage anymore. Any help would be great
Consider this example:
saveHeader() {
this.state.shoeList[0].id = 'newid'
this.setState({ shoeList: this.state.shoeList })
}
setState() checks if the values have changed, and if not, it does not update the component. Changing a nested value does not change the reference to the array, which means that simply calling setState() is not enough.
There are two ways around this. The first is to use forceUpdate():
saveHeader() {
this.state.shoeList[0].id = 'newid'
this.forceUpdate()
}
This forces the component to re-render, even though the state didn't change.
The second way is to actually change the shoeList array by creating a new one:
saveHeader() {
let newShoeList = this.state.shoeList.slice()
newShoeList[0].id = 'newid'
this.setState({ shoeList: newShoeList })
}
Using .slice() on an array creates a new array that is completely identical. But because it is a new array, React will notice that the state changed and re-render the component.
I'm fetching some data from backend, working around with the messages array obtained, and setting it through Redux, synchronously, I execute Navigation.push(). Noticed that since render is being called due to the Redux call, it's throwing a warning on console about the state change on unmount component because it's already rendering the new screen when that happens.
Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method.
This is my function where the magic begins (?
_getGroupMessages(groupData) {
this._chatClient.getMessages({chatGroupId: groupData.key, limit: this.limit, offset: this.offset })
.then(msgs => {
let {userInfo} = this.props;
// set new offset to retrieve more messages later if any
this.offset = this.offset + msgs.length;
let messages = this._handleRetrievedGroupMessages(msgs, groupData);
this.props.onAddChatMessage(messages, true);
Navigation.push(this.props.componentId, {
component: {
name: 'myapp.ChatScreen',
passProps: {
onRefreshReadByGroup: this._onRefreshReadByGroupId,
onHandleTyping: this._onHandleTyping,
isTargetTyping: this.state.isTargetTyping,
reloadMoreMessages: this._getMoreGroupMessages,
userId: userInfo.id,
name: userInfo.fullName || userInfo.name,
chatData: groupData
},
options: {
animated: true,
bottomTabs: {
visible: false,
drawBehind: true,
animate: true
}
}
}
});
})
.catch(error => {
console.log(error);
});
}
I'm not doing any setState in those functions, the only thing executing is the userReducer to set the redux messages state when I call this.props.onAddChatMessage(messages, true);
I know it's this because i commented out the entire Navigation.push call and the warning is not thrown of course, because the screen isn't unmounting.
I attempted to put the Navigation.push within a setTimeout of 2s and it worked. But that is super dirty.
How can I make this work?
It's a chat list group, that whenever I tap on a group, it takes me to the actual chat. Hence, I need to retrieve the group messages by key and take the user to the chat screen.
Any help is appreciated. (I'd prefer not implementing the this._isMounted workaround since it's also very dirty)
Thanks in advance.