I am trying to show values by types, but it return only one value
filerBuilding(value) {
this.state.buildings.map((item) => {
if (value.target.value === item.buildingType) {
this.setState({
buildings: this.state.buildings.splice(this.state.buildings.length),
});
let data = [];
data.push(item);
this.setState({ buildings: data });
}
else{
}
});
}
#Giacomo's comment addresses the issue. To translate it into an implementation using filter:
function filterBuilding(value) {
const filtered = this.state.buildings.filter(
item => value.target.value === item.buildingType
);
this.setState({ buildings: filtered });
}
Related
In my React project I have a function within a class-based component that handles video uploads. It is working as expected and desired. However, I realized upon inspection that it violates React's don't mutate state mandate. I think that's the case, though I want to ensure that's true, and that the solution I've come up with deals with this.
Here is my component state:
state = {
streamingRes: {},
uploadFailed: false
}
My initial function looked like this (notice there are 3 places where I am setting the state):
fileUploadHandler = (id, file, fileId) => {
const isValid = this.validateVideoFileType(file);
if(!isValid) this.props.showError(`${file.name} is of the wrong file type (${file.type}). File must be an acceptable video format.`);
let dataStream = io.Stream.createStream();
io.Socket.on('userVideos.uploadProgress', (data) => {
this.setState( { streamingRes: data });
if(fileId === data.data.guid) {
this.uploadCompletionPercentage = data.data.progress;
}
});
io.Stream(io.Socket).emit('userVideos.upload', dataStream, {
guid: fileId,
size: file.size
}, (data) => {
if(data.status === "failure") {
this.props.onUploadFailed();
this.setState( { uploadFailed: true })
}
else if(data.status === "success") {
this.props.upload(id)
}
});
this.setState( { uploadFailed: false });
io.Stream.createBlobReadStream(file).pipe(dataStream);
return;
}
To avoid mutating state I updated this function to look like this:
handleFileUpload = (id, file, fileId) => {
let newState = {...this.state};
const isValid = this.validateVideoFileType(file);
if(!isValid) this.props.showError(`${file.name} is of the wrong file type (${file.type}). File must be an acceptable video format.`);
let dataStream = io.Stream.createStream();
io.Socket.on('userVideos.uploadProgress', (data) => {
this.setState( { streamingRes: data });
if(fileId === data.data.guid) {
this.uploadCompletionPercentage = data.data.progress;
}
});
io.Stream(io.Socket).emit('userVideos.upload', dataStream, {
guid: fileId,
size: file.size
}, (data) => {
if(data.status === "failure") {
this.props.onUploadFailed();
newState.uploadFailed = true;
this.setState( { uploadFailed: newState.uploadFailed });
}
else if(data.status === "success") {
this.props.upload(id)
}
});
newState.uploadFailed = false;
this.setState( { uploadFailed: newState.uploadFailed });
io.Stream.createBlobReadStream(file).pipe(dataStream);
return;
}
Notice I am using the spread operator right at the top of the function now. My question is: does this effectively deal with the issue of avoiding state mutation?
Yes, you have avoided mutating state. However, your way of doing it is completely unnecessary because there is no need to copy the state into a new object if you don't use that object.
Instead of:
newState.uploadFailed = true;
this.setState( { uploadFailed: newState.uploadFailed });
You can simply do:
this.setState({ uploadFailed: false });
There was no problem in your code in the first place.
I tried to render a list of items by Vuejs, the code below is a simplified version of it. Basically, I need it to display data, the state and data appears in VueDevTool but not on the page.
<template>
<div>
<h1>{{this.sendersList.length}}</h1> <!-- 0 -->
<h1>{{senders.length}}</h1> <!-- 0 -->
</div>
</template>
<script>
export default{
data () {
return {
sendersList: []
}
},
created () {
this.$store.dispatch('getAllSenders', {
app_id: this.$route.params.chat_id
}).then(response => {
this.sendersList = response
})
},
computed: {
senders(){
return this.$store.getters.getAllSenders
}
}
}
</script>
Store code returns data as normal, VueDevtool can see it but I cant find away to render it on the front-end
getAllMessages(context, data){
return new Promise((resolve, reject) => {
axios.post('messages/getAllMessages', {
sender_id: data.sender_id
}).then(response => {
let payload = []
for (let index = 0; index < response.data.length; index++) {
payload.push({
message_id: response.data[index].message_id,
message_content: response.data[index].message_content,
message_type: response.data[index].message_type,
message_sentiment: response.data[index].message_sentiment,
sender_id: response.data[index].sender_id,
user_id: response.data[index].user_id,
from_sender: response.data[index].from_sender,
created_date: response.data[index].created_date,
})
}
context.commit('getAllMessages', payload)
resolve(payload)
}).catch(error => {
reject(error)
})
})
},
Try change this
<h1>{{this.sendersList.length}}</h1>
To this
<h1>{{sendersList.length}}</h1>
I have problem, in the code below I'm trying to console.log only name of the playLists from state with console.log(this.state.playLists.name); I get undefined.
getPlaylist() {
spotifyApi.getUserPlaylists().then((response) => {
if (response.items) {
const items = response.items;
console.log(items);
const playListsId = items.map((obj) => {
const playList = {
name: obj.name,
id: obj.id,
};
return playList;
});
console.log(playListsId);
this.setState({
playLists: playListsId,
});
}
console.log(this.state.playLists.name);
});
}
Since this.state.playLists is an array you cannot get name on it. you have to get the name of all elements in an array.
Try this in place of console.log(this.state.playLists.name);
this.state.platLists.map(playList => console.log(playList.name));
I am using Draftjs and Draftjs mention plugin. When there is a suggestion for mention name it renders fine but if suggestion doesn't exist and I use # followed by random text it crashes. Can anyone help me out with this. Will be very grateful. Thank you.
this.mentionMembersPlugin = createMentionPlugin({
entityMutability: "IMMUTABLE",
positionSuggestions,
mentionTrigger: "#",
mentionPrefix: "",
supportWhitespace: true
});
onChangeEditor = editorState => {
this.setState({ emptyField: false });
this.setState({ editorState });
};
onSearchMemberChange = ({ value }) => {
this.setState({
suggestionMembers: defaultSuggestionsFilter(
value,
this.state.mentionMembers
)
});
};
handleKeyCommand(command: string): DraftHandleValue {
if (command === "save_teamsync") {
// Perform a request to save your contents, set
// a new `editorState`, etc.
this.add_taskComment();
return "handled";
}
return "not-handled";
}
add_taskComment() {
let newData = convertToRaw(this.state.editorState.getCurrentContent());
let checkText = newData.blocks[0].text;
this.setState({ clicked: true });
var r = JSON.stringify(
convertToRaw(this.state.editorState.getCurrentContent())
);
//e.preventDefault();
if (checkText.trim().length !== 0) {
if (this.isValid(r)) {
var data = {};
data.text = r;
data.mentionMembers = r.entityMap;
this.props
.addTaskComment(this.props.task._id, this.showTags, data)
.then(res => {
if (res.data.success) {
const editorState = EditorState.push(
this.state.editorState,
ContentState.createFromText("")
);
this.setState({
editorState: EditorState.moveFocusToEnd(editorState)
});
//this.setState({ editorState: EditorState.moveFocusToStart(EditorState.createEmpty()), clicked:false });
this.lastComment.scrollIntoView({ behavior: "smooth" });
}
});
}
} else {
this.setState({ isCommentEmpty: true });
}
}
<Editor
blockStyleFn={"myBlockStyleFn"}
editorState={this.state.editorState}
onChange={this.onChangeEditor}
plugins={this.plugins}
handleKeyCommand={this.handleKeyCommand}
keyBindingFn={this.myKeyBindingFn}
placeholder="Write a comment"
ref={element => {
this.editor = element;
}}
/>
<MentionMembersSuggestions
onSearchChange={this.onSearchMemberChange}
suggestions={this.state.suggestionMembers}
/>
This are all the code that are being used to render the comments.
This is the error I am getting "Unhandled Rejection (TypeError): this.props.getEditorState is not a function".
I don't think this is difficult, I just can't figure out the best way to do it. This function is creating an array, from a group of checkboxes. I then want to break up the array and create an array of objects, because each object can have corresponding data. How do I filter out existing rolesInterestedIn.roleType.
handleTypeOfWorkSelection(event) {
const newSelection = event.target.value;
let newSelectionArray;
if(this.state.typeOfWork.indexOf(newSelection) > -1) {
newSelectionArray = this.state.typeOfWork.filter(s => s !== newSelection)
} else {
newSelectionArray = [...this.state.typeOfWork, newSelection];
}
this.setState({ typeOfWork: newSelectionArray }, function() {
this.state.typeOfWork.map((type) => {
this.setState({
rolesInterestedIn: this.state.rolesInterestedIn.concat([
{
roleType: type,
}
])
}, function() {
console.log(this.state.rolesInterestedIn);
});
})
});
}
UDPATE
rolesInterestedIn: [
{
roleType: '',
experienceYears: ''
}
],
Because each time you do setState you are concatenating the new value to the prev one in rolesInterestedIn array. Add new value only when you are adding new item, otherwise remove the object from both the state variable typeOfWork and rolesInterestedIn.
Try this:
handleTypeOfWorkSelection(event) {
const newSelection = event.target.value;
let newSelectionArray, rolesInterestedIn = this.state.rolesInterestedIn.slice(0);
if(this.state.typeOfWork.indexOf(newSelection) > -1) {
newSelectionArray = this.state.typeOfWork.filter(s => s !== newSelection);
rolesInterestedIn = rolesInterestedIn.filter(s => s.roleType !== newSelection)
} else {
newSelectionArray = [...this.state.typeOfWork, newSelection];
rolesInterestedIn = newSelectionArray.map((workType) => {
return {
roleType: workType,
experienceYears: '',
}
});
}
this.setState({
typeOfWork: newSelectionArray,
rolesInterestedIn: rolesInterestedIn
});
}
Suggestion: Don't use multiple setState within a function, do all the calculation then use setState once to update all the values in the last.