I have several JavaScript files that I create enums. for example:
source.enum.js
const enumUtils = require('../enum.utils');
const EmailAddressesSourceType = enumUtils.createEnum([
['DIRECTORY', 'directory'],
['FILE', 'file'],
['ARRAY', 'array']
]);
module.exports = { EmailAddressesSourceType };
The enum.utils.js is just a file that do the simple function of creating an enum from array:
class EnumUtils {
constructor() { }
// This method takes a map of elements and converts them to freeze objects (an enum-like object).
createEnum(mapItems) {
if (!mapItems || mapItems.length <= 0) {
throw new Error(`No array received: ${mapItems} (1000000)`);
}
const mapList = new Map([...mapItems]);
const symbolMap = {};
mapList.forEach((value, key) => { symbolMap[key] = value; });
return Object.freeze(symbolMap);
}
}
const enumUtils = new EnumUtils();
module.exports = enumUtils;
Now since I have 5-6 js files with enums, I want to avoid 'const enumUtils = require('../enum.utils');' in each of them, and do it all together in index.js file, something like this:
const { EmailAddressStatus, EmailAddressType, SendEmailStepName } = require('./files/emailAddress.enum');
const { Placeholder } = require('./files/placeholder.enum');
const { EmailAddressesSourceType } = require('./files/sources.enum');
const { Mode, Status, Method } = require('./files/system.enum');
const { StatusIcon, Color, ColorCode } = require('./files/text.enum');
const createEnum = (mapItems) => {
if (!mapItems || mapItems.length <= 0) {
throw new Error(`No array received: ${mapItems} (1000000)`);
}
const mapList = new Map([...mapItems]);
const symbolMap = {};
mapList.forEach((value, key) => { symbolMap[key] = value; });
return Object.freeze(symbolMap);
};
module.exports = {
createEnum(Color), createEnum(ColorCode), createEnum(EmailAddressStatus), createEnum(EmailAddressType), createEnum(EmailAddressesSourceType),
createEnum(Method), createEnum(Mode), createEnum(Placeholder), createEnum(SendEmailStepName), createEnum(Status), createEnum(StatusIcon)
};
But, there are compilation error in:
module.exports = {
createEnum(Color), createEnum(ColorCode), createEnum(EmailAddressStatus), createEnum(EmailAddressType), createEnum(EmailAddressesSourceType),
createEnum(Method), createEnum(Mode), createEnum(Placeholder), createEnum(SendEmailStepName), createEnum(Status), createEnum(StatusIcon)
};
My question is, there is a workaround so enable me to reduce the 'const enumUtils = require('../enum.utils');' in each file of the enums js file?
Thanks!
UPDATE 1
The error I'm getting is this:
The current status of the file (before I was trying to refactor) - It works OK:
index.js
const { EmailAddressStatus, EmailAddressType, SendEmailStepName } = require('./files/emailAddress.enum');
const { Placeholder } = require('./files/placeholder.enum');
const { EmailAddressesSourceType } = require('./files/sources.enum');
const { Mode, Status, Method } = require('./files/system.enum');
const { StatusIcon, Color, ColorCode } = require('./files/text.enum');
module.exports = {
Color, ColorCode, EmailAddressStatus, EmailAddressType, EmailAddressesSourceType,
Method, Mode, Placeholder, SendEmailStepName, Status, StatusIcon
};
This guy, guy-incognito, solved for me the issue. Now it works like a charm. Thanks man!
const { EmailAddressStatus, EmailAddressType, SendEmailStepName } = require('./files/emailAddress.enum');
const { Placeholder } = require('./files/placeholder.enum');
const { EmailAddressesSourceType } = require('./files/sources.enum');
const { Mode, Status, Method } = require('./files/system.enum');
const { StatusIcon, Color, ColorCode } = require('./files/text.enum');
const createEnum = (mapItems) => {
if (!mapItems || mapItems.length <= 0) {
throw new Error(`No array received: ${mapItems} (1000000)`);
}
const mapList = new Map([...mapItems]);
const symbolMap = {};
mapList.forEach((value, key) => { symbolMap[key] = value; });
return Object.freeze(symbolMap);
};
module.exports = {
Color: createEnum(Color),
ColorCode: createEnum(ColorCode),
EmailAddressStatus: createEnum(EmailAddressStatus),
EmailAddressType: createEnum(EmailAddressType),
EmailAddressesSourceType: createEnum(EmailAddressesSourceType),
Method: createEnum(Method),
Mode: createEnum(Mode),
Placeholder: createEnum(Placeholder),
SendEmailStepName: createEnum(SendEmailStepName),
Status: createEnum(Status),
StatusIcon: createEnum(StatusIcon)
};
In the line setVotedPosts([...previousVotedPosts, postId]);
I'm trying to get the previous value of votedPosts, but I'm getting back the newest value.
full code : https://github.com/silvertechguy/reddit-clone/blob/main/src/components/vote-buttons.js
App live : https://reddit-clone-official.vercel.app/
const VoteButtons = ({ post }) => {
const [isVoting, setVoting] = useState(false);
const [votedPosts, setVotedPosts] = useState([]);
useEffect(() => {
const votesFromLocalStorage =
JSON.parse(localStorage.getItem("votes")) || [];
setVotedPosts(votesFromLocalStorage);
}, []);
const handleDisablingOfVoting = (postId) => {
const previousVotedPosts = votedPosts;
setVotedPosts([...previousVotedPosts, postId]);
localStorage.setItem(
"votes",
JSON.stringify([...previousVotedPosts, postId])
);
};
const handleClick = async (type) => {
setVoting(true);
// Do calculation to save the vote.
let upVotesCount = post.upVotesCount;
let downVotesCount = post.downVotesCount;
const date = new Date();
if (type === "upvote") {
upVotesCount = upVotesCount + 1;
} else {
downVotesCount = downVotesCount + 1;
}
await db.collection("posts").doc(post.id).set({
title: post.title,
upVotesCount,
downVotesCount,
createdAt: post.createdAt,
updatedAt: date.toUTCString(),
});
// Disable the voting button once the voting is successful.
handleDisablingOfVoting(post.id);
setVoting(false);
};
const checkIfPostIsAlreadyVoted = () => votedPosts.includes(post.id);
Problem
const previousVotedPosts = votedPosts;
In JavaScript, arrays are reference types, so you can't just create a new copy of an array using =.
Try this solution
Clone array using spread syntax(...).
const handleDisablingOfVoting = (postId) => {
const previousVotedPosts = [...votedPosts];
setVotedPosts([...previousVotedPosts, postId]);
localStorage.setItem(
"votes",
JSON.stringify([...previousVotedPosts, postId])
);
};
how can I get the Index of city cliked and pass it to function Daily.js
exemple when user change location to differnt city I want to change the Url
in the list location 1 => url 1
location2 => url 2
...
function Daily({ locationProps = 1, root }) {
const context = useContext(ThemeContext);
const localization = useCallback(() => {
if (root && cookies.get("location") !== undefined) {
return cookies.get("location");
}
return locationProps;
}, [locationProps, root]);
const handleClick = event => {
window.focus();
notification.close(event.target.tag);
};
const openNav = () => {
document.getElementById("sidenav").style.width = "100%";
};
const closeNav = e => {
e.preventDefault();
document.getElementById("sidenav").style.width = "0";
};
const _data = useRef(new Data(INDEX)); // -----> How to pass INDEX here !
const getTimes = () => _data.current.getTimes();
const times = useState(()=>getTimes());
data.json
location [
liste of location
],
URL [
list of url
]
Hi i want to return the promise that gets resolved when the first poll finishes...
I have a start_polling method and i want to modify it such that it returns a promise that gets resolved when the items_promise gets resolved...i am not sure how to do it.
What i have tried?
i have created a promise in start_polling method that gets resolved when the item_promise_finish() is executed in then method of items_promise.
Once this promise in start_polling is resolved then i call handle_location method.
It works fine but sometimes i get error cannot read property then of undefined.
How can i fix it.
below is the code,
componentDidUpdate(prevProps, prevState) {
const {state, props} = this;
const current_id = props.item && props.item.id;
const prev_id = prevProps.item && prevProps.item.id;
if (current_id !== prev_id) {
this.stop_polling();
this.setState(this.get_initial_state(), () => {
this.start_polling();
});
} else {
const prev_poll = this.should_poll(prevProps, prevState);
const next_poll = this.should_poll(props, state);
if (prev_poll !== next_poll) {
if (next_poll) {
this.start_polling();
} else {
this.stop_polling();
}
}
if (this.props.location.search) {
this.start_polling().then(() => {
this.handle_location();
})
}
start_polling = () => {
if (this.should_poll(this.props, this.state)) {
this.poll();
return new Promise((resolve) => {
this.item_promise_finish=resolve;
});
}
};
poll = () => {
let still_polling = true;
if (this.cancel_poll_request) {
this.cancel_poll_request();
}
});
const items_promise = client.get_items(this.props.item.id,
cancel_poll_promise);
items_promise.then((request) => {
const next_items = [];
let something_changed = false;
for (const new_item of request.response) {
const old_item = this.state.items.find(
old_item =>
old_item.id === new_item.id);
if (old_item) {
next_items.push(old_item);
} else {
something_changed = true;
next_items.push(new_item);
}
}
if (something_changed) {
const next_state = {items: next_items};
this.setState(next_state);
}
}).then(() => {
if (still_polling) {
this.poll_timeout = setTimeout(this.poll, 100s);
}
this.item_promise_finish();
}).catch(this.props.notifications.request_error);
};
Could someone let me know where i am going wrong or what to be done to fix this. thanks.
I'm trying to obtain a list of all the keys defined on a normalizr schema, & have written a function that does what I need for a simple schema:
export const collectAttributes = target => {
const schemaKeys = []
if (target.hasOwnProperty('_key')) {
schemaKeys.push(target._key)
}
const definitions = Object.keys(target).filter(key => key[0] !== '_')
definitions.forEach(key => {
collectAttributes(target[key]).forEach(attribute => schemaKeys.push(attribute))
})
return schemaKeys
}
However, this fails on a nested schema definition with a Maximum call stack size exceeded error, as illustrated with this test case:
describe('collectAttributes', () => {
it('should collect all unique collections defined on a recursive schema', () => {
const nodeSchema = new schema.Entity('nodes', {})
const nodeListSchema = new schema.Array(nodeSchema)
nodeSchema.define({ children: nodeListSchema })
expect(collectAttributes(nodeSchema)).toEqual(['nodes'])
})
})
If anyone has ideas on how to collect the already visited schemas such that the recursive function halts, they would be much appreciated.
I figured it out in the end - solution below:
export const isSchema = target => {
if (Array.isArray(target)) {
return target.length ? isSchema(target[0]) : false
} else {
return target.hasOwnProperty('schema') || target instanceof schema.Entity || target instanceof schema.Array
}
}
const recursiveCollect = (target, visited = []) => {
const entities = []
const visitedSchemas = [...visited]
if (isSchema(target)) {
entities.push(target.key)
visitedSchemas.push(target)
}
if (Array.isArray(target) || target instanceof schema.Array) {
/*
* If the current target is an ArraySchema, call `recursiveCollect`
* on the underlying entity schema
*/
return recursiveCollect(target.schema, visitedSchemas)
}
Object.keys(target.schema).filter(x => x[0] !== '_').forEach(definition => {
const childSchema= target.schema[definition]
const alreadyVisited = visitedSchemas.includes(childSchema)
if (isSchema(childSchema) && !alreadyVisited) {
/* Only call `recursiveCollect` on the child schema if it hasn't
* already been encountered
*/
const result = recursiveCollect(childSchema, visitedSchemas)
if (result.entities) {
result.entities.forEach(x => entities.push(x))
}
if (result.visitedSchemas) {
result.visitedSchemas.forEach(x => visitedSchemas.push(x))
}
}
})
return { entities, visitedSchemas }
}
export const collectAttributes = target => {
const { entities } = recursiveCollect(target)
return entities
}