Create unique array while push Object to array in react useState hook - javascript

I am declaring react state as below
const [selectedFiles, setselectedFiles] = useState([]);
Using them in function as below
function handleAcceptedFiles(files) {
files.map((file) =>
Object.assign(file, {
preview: URL.createObjectURL(file),
formattedSize: file.size,
})
);
selectedFiles.length === 0 ? setselectedFiles(files) : setselectedFiles(oldFiles => [...oldFiles,...files])
}
At this point how can we add only new file and remove duplicate file
setselectedFiles(oldFiles => [...oldFiles,...files])

You could create a lookup object with key-value pairs of filePreview-file and grab values from that
function handleAcceptedFiles(files) {
const pendingFiles = files.map(file =>
Object.assign(file, {
preview: URL.createObjectURL(file),
formattedSize: file.size
})
)
const dedupFiles = Object.values(
[...selectedFiles, ...pendingFiles].reduce((lookup, file) => {
if (lookup[file.name] === undefined) {
lookup[file.name] = file
}
return lookup
}, {})
)
setselectedFiles(dedupFiles)
}

Maybe this is what you need?
function handleAcceptedFiles(files) {
// Map over the current selection of files, generate required fields
const newFiles = files.map(file => {
return Object.assign(file, {
preview: URL.createObjectURL(file),
formattedSize: file.size,
});
});
// Find non-duplicate entries in previously selected files
const nonDupFiles = selectedFiles.filter(oldFile => {
const index = newFiles.findIndex(newFile => newFile.preview === oldFile.preview);
return index === -1; // index -1 => file wasn't found => non duplicate
});
// Concat of new files and non-dup files is what we need in state
setselectedFiles(newFiles.concat(nonDupFiles));
}

Related

How to delete multiple url params

There is a problem with deleting several string parameters. Only the last parameter is being deleted now.
upd: I did not specify that I wanted to achieve the ability to remove specific parameter values
this code does not work correctly:
const updateFiltersSearchParams = (paramKey, newValue) => {
const isParamExist = searchParams.getAll(paramKey).includes(newValue);
if (!isParamExist) {
searchParams.append(paramKey, newValue);
setSearchParams(searchParams);
} else {
const updatedSearchParams = new URLSearchParams(
[...searchParams].filter(
([key, value]) => key !== paramKey || value !== newValue
)
);
setSearchParams(updatedSearchParams);
}
};
const handleDeleteParams = () => {
[...checkboxParams].forEach((param) => {
updateFiltersSearchParams("selected", param);
});
};
Sandbox
change your handleDeleteParams function with this
const handleDeleteParams = () => {
setSearchParams([]);
};
If you want to delete *only the selected (or any specific queryString key) queryString parameters you can use the delete method of the URLSearchParams object, then enqueue the params URL update.
const handleDeleteParams = (key) => {
searchParams.delete(key);
setSearchParams(searchParams);
};
...
<button type="button" onClick={() => handleDeleteParams("selected")}>
Clear all "selected" params
</button>
Solved the problem by modifying the function like this
const toggleSearchParams = (params) => {
const newSearchParams = [...searchParams];
for (const prevParam of params) {
const index = newSearchParams.findIndex(
(newParam) =>
prevParam[0] === newParam[0] && prevParam[1] === newParam[1]
);
if (index === -1) {
newSearchParams.push(prevParam);
} else {
newSearchParams.splice(index, 1);
}
}
setSearchParams(new URLSearchParams(newSearchParams));
};
const handleChangeCheckBoxValue = (e) => {
toggleSearchParams([["selected", e.target.value]]);
};
const handleDeleteParams = () => {
toggleSearchParams(checkboxParams.map((param) => ["selected", param]));
};

How to make an array of objects from dynamic values?

I have the following function
const extractTestCases = () => {
const filterFile = files.filter(test => test.includes('.test.ts'))
filterFile.forEach(testsuite => {
const testSuites = fs.readFileSync(testsuite, { encoding: "utf8" });
testCases.push(regexMatcher(testSuites, TestRegex, 1))
})
return testCases;
}
filterFile is an array for multiple files where I'm making forEach loop to extract some information from each file, what I want to do is to return an array of objects like this
[{"name of the file (testSuite)":["extracted value from this file regexMatcher(testSuites, TestRegex, 1)"]},{"testSuite2":["","",""]},...]
Try something like this :
const extractTestCases = () => {
const filesArray = []
const filterFile = files.filter(test => test.includes('.test.ts'))
filterFile.forEach(testsuite => {
const testSuites = fs.readFileSync(testsuite, { encoding: "utf8" });
testCases.push(regexMatcher(testSuites, TestRegex, 1))
filesArray.push({[testsuite]: regexMatcher(testSuites, TestRegex, 1)})
})
return filesArray;
}

How to push a file in a base64 format in array?

I am trying to push to the data array the object with the file and file base64 format in getBase64.
But when I console log data array it is empty, also I can turn file into base64 format. But I don't understand why the push method in getBase64 doesn't work. How do I get bot the file and file base 64.
export default function UploadDoc({ setInputs }) {
function beforeUpload(file) {
const isRightType =
file?.type === "application/pdf" ||
file?.type === "application/xlsx" ||
file?.type === "image/jpeg" ||
file?.type === "application/csv" ||
file?.type === "text/plain";
if (!isRightType) {
message.error("You can only upload PDF, TXT, JPEG, CSV or XLSX files!");
}
const isLt2M = file?.size / 1024 / 1024 < 2;
if (!isLt2M) {
message.error("PDF must be smaller than 2MB!");
}
setFileList((state) => (state ? [...state, file] : [file]));
return isRightType && isLt2M;
}
const overrideRequest = ({ file, onSuccess, onError }) => {
// <Upload/> renders another component (rc-upload) as its child which handles the actual AJAX upload.
// You can override this behaviour by passing a customRequest prop to <Upload/>
const isRightType =
file?.type === "application/pdf" ||
file?.type === "image/jpeg" ||
file?.type === "application/csv" ||
file?.type === "text/plain";
if (isRightType) {
setTimeout(() => {
onSuccess("ok");
}, 1);
} else {
setTimeout(() => {
onError("ok");
}, 1);
}
};
const getBase64 = (file) =>
new Promise((resolve) => {
// turns file data in loggable and readable data from javascript
const reader = new FileReader();
reader.onloadend = () => resolve(reader.result);
reader.readAsDataURL(file);
});
const dispatch = useDispatch();
const fileList = useSelector((state) => state.filesFileListReducer);
const handleUploadChange = (info) => {
if (info.file.status === "error") {
console.log("error", info.file);
}
if (info.file.status === "done") {
// Get this url/data from response in real world.
const arr = [];
info.fileList.forEach(async (file) => {
const fileInfo = await getBase64(file.originFileObj);
const infoOnUploadedFile = { base64: fileInfo, fileObj: file };
console.log("file info", infoOnUploadedFile);
arr.push(infoOnUploadedFile);
});
console.log("data", arr);
}
};
return (
<Upload
{...{
multiple: true,
beforeUpload: (file) => beforeUpload(file),
accept: ".txt, .csv, .jpeg, .pdf",
customRequest: (info) => overrideRequest(info),
onChange: (info) => handleUploadChange(info),
onRemove: (file) => {
const newFileList = fileList?.filter(
(fileGrp) => fileGrp.fileObj !== file
);
dispatch(setFileList(newFileList));
setInputs((state) => ({
...state,
docs: newFileList && newFileList.map((file) => file?.fileBase64),
}));
},
}}
>
<Button icon={<UploadOutlined />} style={{ width: "100px" }} />
</Upload>
);
}
You are trying to get an object before his availability.
Such as you want to get the value but directly, You can use async/await feature (wiki).
For you, something like this will fix it :
const getBase64 = (blob: Blob) => {
return new Promise((resolve) => {
const reader = new FileReader()
reader.onloadend = () => resolve(reader.result)
reader.readAsDataURL(blob) // read blob
})
}
const obj = await getBase64(resBlob); // wait until method not finished
// now you can check if obj is defined and push it into array

Delete Function using .filter Method

I am creating a note taking app and am getting stuck on my deleteNote function. I am needing to use the .filter method to remove notes w/ an assigned id and keep the ones not associated to that id. Here is my code so far.
const fs = require("fs");
const util = require("util");
// returns a unique ID for our returns
const uuidv1 = require("uuid/v1");
// creates a promified version of fs.readfile and writefile
const readFileAsync = util.promisify(fs.readfile);
const writeFileAsync = util.promisify(fs.writefile);
class Store {
read() {
return readFileAsync("./db/db.json", "utf8");
}
write(note) {
return writeFileAsync("./db/db.json", JSON.stringify(note));
}
getNotes() {
return this.read().then(notes => {
let parsedNotes;
try {parsedNotes = [].concat(JSON.parse(notes))}
catch (err) {
parsedNotes = [];
}
return parsedNotes;
})
}
// example of destructuring -- im taking the title, text string and destructuring it to add a unique id.
addNote(note) {
const {title, text} = note;
const newNote = {title, text, id: uuidv1()};
return this.getNotes()
.then(notes => [...notes, newNote]);
.then(updatedNotes => this.write(updatedNotes));
.then(() => newNote);
}
// delete note is going to take in an id and use a .filter to only keep the notes that do not include that id.
deleteNote() {
}
}
module.exports = new Store();
You already know you're filtering, so just do it:
deleteNote(id) {
return this.getNotes()
.then(notes => notes.filter(note => note.id !== id))
.then(updatedNotes => this.write(updatedNotes));
}
Try this one which includes returning deleted note.
async deleteNote(id) {
const notes = await this.getNotes();
const filtered = notes.filter((note) => note.id !== id);
await this.write(filtered);
const deleted = notes.filter((note) => note.id === id);
return deleted;
}

Update elements of array of object when one element is changed [duplicate]

I've got add
I've got delete
now I need modify
add just adds to the pile haphazardly
delete is able to do it's work with surgical precision because it uses key to find it's culprit :
addInput = (name) => {
const newInputs = this.props.parameters;
newInputs.push({
name,
key: uuid(),
value: { input: '' },
icon: { inputIcon: 0 },
});
this.setState({
newInput: newInputs,
});
this.props.exportParameter(newInputs);
};
removeInput = (key) => {
const newInputs = this.props.parameters.filter(x => x.key !== key);
this.setState({
newInput: newInputs,
});
this.props.exportParameter(newInputs);
};
how do I modify (for example set the value back to '' without deleting and recreating the item) ?
modifyInput = (key) => {
?????
};
You can use Array.prototype.find()
modifyInput = (key) => {
const match = this.props.parameters.find(x => x.key === key);
// do stuff with matched object
};
You can map through the parameters and then modify when you find a match:
modifyInput = (key) => {
const newInputs = this.props.parameters.map(x => {
if (x.key === key) {
x.modification = true;
}
return x;
});
this.setState({
newInput: newInputs,
});
this.props.exportParameter(newInputs);
};
var empMap= {};
//initialize empMap with key as Employee ID and value as Employee attributes:
//Now when salary updated on UI from 100 - 300 you can update other fields
var e=empMap[id];
if(e){
e.Salary=newSalary;
e.YearlySalary = newSalary*12;
e.Deductions = e.YearlySalary*0.2;
empMap[id]=e;
}

Categories

Resources