I use the following code to show tree items,
https://github.com/microsoft/vscode-extension-samples/tree/master/tree-view-sample
The items which is shown in the tree is related to a file, if the file changed the number of the tree items should be changed accordingly(using createFileSystemWatcher which works ok), currently I’ve add the code of the file watcher and when debug it stops there (on the getChildren function when I'm changing the file) and I see that I’ve provided the new updated entries (in the code),however the tree doesn’t refreshed with the new data, any idea what am I missing here ? somehow the new updated data is not reflected in the tree. as I new to this topic maybe I miss something. if the code is OK and there is a bug or this is not supported please let me know.
export class TaskTreeDataProvider implements vscode.TreeDataProvider<TreeItem> {
private _onDidChangeTreeData: vscode.EventEmitter<TreeItem | null> = new vscode.EventEmitter<TreeItem | null>();
readonly onDidChangeTreeData: vscode.Event<TreeItem | null> = this
._onDidChangeTreeData.event;
private eeake: Promise<TreeItem[]> | undefined = undefined;
private autoRefresh: boolean = true;
constructor(private context: vscode.ExtensionContext) {
this.autoRefresh = vscode.workspace
.getConfiguration(“sView")
.get("autorefresh");
let filePath = this.fileName;
let fileWatcher = vscode.workspace.createFileSystemWatcher(filePath);
fileWatcher.onDidChange(() => (this.eeake = this.getChildren()), this.refresh());
}
refresh(): void {
this._onDidChangeTreeData.fire();
}
public async getChildren(task?: TreeItem): Promise<TreeItem[]> {
let tasks = await vscode.tasks
.fetchTasks({ type: “run” })
.then(function (value) {
return value;
});
let entry: TreeItem[] = [];
if (tasks.length !== 0) {
for (var i = 0; i < tasks.length; i++) {
entry[i] = new TreeItem(
tasks[i].definition.type,
tasks[i].name,
{
command: “sView.executeTask",
title: "Execute",
arguments: [tasks[i]]
}
);
}
}
return entry;
}
getTreeItem(task: TreeItem): vscode.TreeItem {
return task;
}
}
class TreeItem extends vscode.TreeItem {
type: string;
constructor(
type: string,
label: string,
collapsibleState: vscode.TreeItemCollapsibleState,
command?: vscode.Command
) {
super(label, collapsibleState);
this.type = type;
this.command = command;
this.iconPath = getIcon();
}
}
If there is something missing please let me know and I add, I'm really stuck with it.
If there is another way to refresh the tree please let me know
Last line in constructor looks suspicious to me.
fileWatcher.onDidChange(() => (this.eeake = this.getChildren()), this.refresh());
I believe you mean:
fileWatcher.onDidChange(() => {
this.eeake = this.getChildren();
this.refresh();
});
Your original code actually immediately invokes this.refresh() in constructor and pass the return value as the 2nd arg to fileWatcher.onDidChange(). this.refresh() wasn't part of the listener passed as 1st arg to onDidChange().
Related
I'm having this weird error:
testObject.ts
import { OobjectA } from './OobjectA';
import { OobjectB } from './OobjectB';
import { OobjectC } from './OobjectC';
export class TestObject{
private _atrrA: number=0;
private _atrr1: string="";
private _atrr2: number = 0;
private _atrr3: number = 0;
private _atrrBt: Date = new Date();
private _atrrC: number =0;
private _atrrD: Date = new Date();
private _atrrError: number = 0;
private _atrr4: number = 0;
private _atrr5: number = 0;
constructor(
oobjectA: OobjectA,
oobjectB: OobjectB,
oobjectC: OobjectC
) {
if (oobjectA !== undefined &&
oobjectB !== undefined &&
oobjectC !== undefined ) {
this._atrrError = oobjectA.atrrError;
this._atrr4 = oobjectB.atrr4;
this._atrr5 = oobjectC.atrr5;
}
}
set atrrA(atrrA){
this._atrrA =atrrA
}
set atrr1(atrr1){
this._atrr1 =atrr1
}
set atrr2(atrr2){
this._atrr2 = atrr2
}
set atrr3(atrr3){
this._atrr3 =atrr3
}
set atrrBt(atrrBt){
this._atrrBt = atrrBt
}
set atrrC(atrrC){
this._atrrC = atrrC
}
set atrrD(atrrD){
this._atrrD = atrrD
}
set atrrError(atrrError){
this._atrrError = atrrError
}
set atrr4(_atrr4){
this._atrr4 = _atrr4
}
set atrr5(atrr5){
this._atrr5 = atrr5
}
get atrrA(){
return this._atrrA
}
get atrr1(){
return this._atrr1
}
get atrr2(){
return this._atrr2
}
get atrr3(){
return this._atrr3
}
get atrrBt(){
return this._atrrBt
}
get atrrC(){
return this._atrrC
}
get atrrD(){
return this._atrrD
}
get atrrError(){
return this._atrrError
}
get atrr4(){
return this._atrr4
}
get atrr5(){
return this._atrr5
}
}
Controller.ts
try{
// ...more code
const oobjectA : OobjectA = new OobjectA ()
oobjectA.atrrError = otherObject[0].atrrError
oobjectB.atrr4 = otherObject2[0].subObject[0].atrr4
const testObject: TestObject = new TestObject(oobjectA, oobjectB, oobjectC)
testObject.atrr1 = "string"
testObject.atrr2 = 1
testObject.atrr3 = 1;
const testObject_id: any = await create_user_function_ejecution_order[5].functionCU(testObject).catch(error => {
create_user_function_ejecution_order[5].status=false
create_user_function_ejecution_order[5].error = error
console.log(error)
})
console.log("testObject",testObject.atrrA?.atrrA)
}catch(e){
// ... more code
}
// ... more code
file.ts
import {db} from "../../connection";
export const insert_data = async(testObject) => {
console.log(testObject)
console.log(testObject._atrrError)
console.log(testObject.atrrError)
console.log(`${testObject.atrrError}`)
console.log(`${testObject._atrrError}`)
const queryString = `
INSERT INTO table (column1, column2, column3, columnError, column4, column5)
VALUES ('${testObject.atrr1}', ${testObject.atrr2}, ${testObject.atrr3}, ${testObject.atrrError} , ${testObject.atrr4}, ${testObject.atr5})
`
console.log(queryString)
const result = await db.query(queryString)
return result[0]
};
output
testObject{
_atrrA: 0,
_atrr1: 'string',
_atrr2: 1,
_atrr3: 1,
_atrrB: 2021-11-24T23:37:42.394Z,
_atrrC: 0,
_atrrD: 2021-11-24T23:37:42.394Z,
_atrrError: 1,
_atrr4: 1,
_atrr5: 1
}
1
1
undefined
undefined
INSERT INTO table (INSERT INTO table (column1, column2, column3, columnError, column4, column5)
VALUES ('string', 1, 1, undefined, 1, 1)
Error: Unknown column 'undefined' in 'field list'
Why it is defined with the value 1 in the cosole.log but in the 3rd console.log it is not defined.
My thought was because some asynchronous thing, but it is in the same file. My second thought was it is taking ownership, but is not a low level language. So my new hypothesis is that the string interpolation have an inside error.
Any other case were it can be other error like this?
devDependencies:
"ts-node": "^10.4.0",
"typescript": "^4.4.4"
nodejs version: v16.13.0
Putting this in an answer just because I need to communicate multiple lines of code which won't be legible in a comment.
When I put this into a file and run that file with nodejs:
const testObject = {
atrr: 1
};
console.log(testObject)
console.log(testObject.atrr)
console.log(`${testObject.atrr}`)
I get this output in the console:
{ atrr: 1 }
1
1
Which is exactly what we would expect. So, apparently there's something different around your object or your environment. The only way I would expect undefined is if the value of the attrr property was something that does not have a .toString() method or if that method returned undefined.
Keep in mind that the template is going to check the type of the value you passed it and, if it isn't a string, it's going to try to convert it to a string. Apparently that string conversion is resulting in undefined.
For any further help, please show exactly how testObject is declared and edit your question to show a minimal, reproducible example.
I have the following code:
const readDataFromSql = () => {
// going to have to iterate through all known activities + load them here
let sql = "[...]"
return new Promise((resolve, reject) => {
executeSqlQuery(sql).then((dict) => {
let loadedData = [];
for (let key in dict) {
let newItemVal = new ItemVal("reading hw", 7121, progress.DONE);
loadedData.push(newItemVal);
}
resolve(loadedData);
});
});
}
ItemVal implementation:
class ItemVal {
constructor(name, time, type) {
this.name = name
this.time = time
this.type = type
}
}
Let's assume that newItemVal = "reading hwj", 5081, progress.PAUSED when readDataFromSql() first runs.
readDataFromSql() is then again called after some state changes -- where it repulls some information from a database and generates new values. What is perplexing, however, is that when it is called the second time, newItemVal still retains its old properties (attaching screenshot below).
Am I misusing the new keyword?
From what I can see in your example code, you are not mutating existing properties but creating a new object with the ItemVal constructor function and adding them to an array, that you then return as a resolved promise. Are you sure the examples you give a correct representation of what you are actually doing
Given that, I'm not sure what could be causing the issue you are having, but I would at least recommend a different structure for your code, using a simpler function for the itemVal.
Perhaps with this setup, you might get an error returned that might help you debug your issue.
const itemVal = (name, time, type) => ({ name, time, type })
const readDataFromSql = async () => {
try {
const sql = "[...]"
const dict = await executeSqlQuery(sql)
const loadedData = dict.map((key) =>
ItemVal("reading hw", 7121, progress.DONE)
)
return loadedData
} catch (error) {
return error
}
};
If the issue is not in the function, then I would assume that the way you handle the data, returned from the readDataFromSql function, is where the issue lies. You need to then share more details about your implementation.
const readDataFromSql = async () => {
let sql = "[...]"
------> await executeSqlQuery(sql).then((dict) => {
Use the await keyword instead of creating a new promise.
I did some modification and found that below code is working correctly, and updating the new values on each call.
const readDataFromSql = () => {
return new Promise((resolve, reject) => {
let loadedData = [];
let randomVal = Math.random();
let newItemVal = new ItemVal(randomVal*10, randomVal*100, randomVal*1000);
loadedData.push(newItemVal);
resolve(loadedData);
});
}
Could you recheck if you are using below line in the code, as it will instantiate object with same properties again and again.
let newItemVal = new ItemVal("reading hw", 7121, progress.DONE);
You can modify your code as below to simplify the problem.
const readDataFromSql = async () => {
// going to have to iterate through all known activities + load them here
let sql = "[...]" // define sql properly
let result = await executeSqlQuery(sql);
let loadedData = [];
for (let row in result) {
let newItemVal = new ItemVal(row.name, row.time, row.type);
loadedData.push(newItemVal);
}
return loadedData;
}
class ItemVal {
constructor(name, time, type) {
this.name = name
this.time = time
this.type = type
}
}
What you are talking about is an issue related to Object mutation in Redux, however, you didn't add any redux code. Anyway, you might be making some mistake while recreating(not mutating) the array.
General solution is the use spread operator as:
loadedData = [ ...loadedData.slice(0) , ...newloadedData]
In Dropdown.js line 188 instead of console.log-ing your variable write debugger;
This will function as a breakpoint. It will halt your code and you can inspect the value by hovering your mouse over the code BEFORE the newItemVal is changed again.
I can see in your screenshot that the newItemVal is modified again after you log it.
I have a problem understanding why the following code does not work.
initializeItems(): void {
this.notesService.load();}
this.notesService.load() creates an object with multiple objects, such as for example notes which then has several attributes such as notes.title. filterList(evt){} is triggered when input is registered in a search bar. When I used a list the code works, but it doesn't work for my objects.
filterList(evt) {
this.initializeItems();
const searchTerm = evt.srcElement.value;
if (!searchTerm) {
return;
}
this.notesService.notes = this.notesService.notes.filter(currentGoal => {
console.log(this.notesService.notes)
if (currentGoal.title && searchTerm) {
if (currentGoal.title.toLowerCase().indexOf(searchTerm.toLowerCase()) > -1) {
return true;
}
return false;
}
});
}
if I remove this.initializeItems(); from filterList(evt) I can see that the filtering works. However, I want to include this.initializeItems() so that when a user uses the backspace the previous filtering is ignored and all objects are displayed again. When I do not include this.initializeItems() I can see that this.notesService.notes is empty after filtering.
When I do include this.initializeItems() no filtering occurs. Could someone tell me why this is not working? When I use, for example, a list with data these functions work fine.
To clarify what initializeItems() does where Note contains an id, title, content and date.
export class NotesService {
public notes: Note[] = [];
public loaded: boolean = false;
constructor(private storage: Storage,private navCtrl: NavController) { }
load(): Promise<boolean> {
return new Promise((resolve) => {
this.storage.get('notes').then((notes) => {
if(notes != null){
this.notes = notes;
}
this.loaded = true;
resolve(true);
Creating my first ReactJS Website and using Node in the back-end, currently in the code that follows I fetch data that I then print on the page. I manage to print the names of the people in a project, their picture and their email from the server BUT the description of the project i get the error :
TypeError: Cannot read property '0' of undefined
Which I do not understand.
Here is the code :
class ProjectPage extends Component {
constructor(props) {
super(props);
this.state = {
user: [],
description: [],
mail: [],
name: [],
};
this.getNames = this.getNames.bind(this);
this.getPictures = this.getPictures.bind(this);
this.getMails = this.getMails.bind(this);
this.getDetails = this.getDetails.bind(this);
}
I create the class and all the elements that are required
componentDidMount() {
console.log("BEGIN componentDidMount");
this.fetchDetails();
this.fetchNames();
this.fetchMails();
console.log("END componentDidMount");
}
Call all the function in my componentDidMount()
fetchDetails() {
console.log("BEGIN fetchDetails()");
let url = 'http://192.168.1.33:8080/getprojectdetails/Aprite';
console.log("url details = " + url);
fetch(url)
.then(results => {
var json = results.json();
return json;
})
.then(data => {
this.setState({ description: data });
})
console.log("END fetchData()");
}
Here is the fetch of the project description
getDetails = () => {
let lines = [];
let nbr = this.state.description.length;
console.log("nbr = " + nbr);
if (nbr){
console.log("lines = " + this.state.description[0].P_Description);
for (let i = 0; i < nbr; i++)
lines.push(<div key={this.state.descripton[i].P_Description}></div>);
}
return (lines);
}
And the function to print the data in the Render() function
But when i try to print this data, the value of nbr passes from 0 to 1 then to 0 again... in the console log I can see the description but it doesn't appear on the website and I don't get it.
Please help me ?
There is a typo in the inner loop inside the getDetails function
You should write this.state.description not this.state.descripton
Hope this solves your problem :)
So with the React render lifecycle system, the componentDidMount will actually happen after the first render. During that first render, you're trying to access the first element of an empty array, which is the error you are seeing.
In order to solve this problem, in your render method, you should have a fallback something to render while we wait for the fetchDetails to return a value from the server. If you want it to render nothing, you can just return null.
ie.
const { description = [] } = this.state;
if (description.length === 0) {
return null;
}
return this.getDetails();
As a side note, in order to avoid having all of those (which gets pretty unmaintainable):
this.getNames = this.getNames.bind(this);
this.getPictures = this.getPictures.bind(this);
this.getMails = this.getMails.bind(this);
this.getDetails = this.getDetails.bind(this);
You can just define them as class properties like so:
getNames = () => {
// do stuff
}
Right now I have a queue (JS array) that is used to store players waiting for a game. I need the FIFO property of a queue so that players who were added to the queue first, get put in a new game first. The problem with a queue is that it doesnt have constant time lookup. It would be great if I could have a map that kept track of the order of insertion (i know that relying on a map to do this is JS is not reliable). If I give the property a value for its insertion order, it would need to be updated if someone leaves the queue, so that isnt helpful either. Anyway around this? A way to get constant lookup and maintain insertion order?
If you don't have memory constraints, maybe you can maintain a map with the queue implemented as a double linked list. Here is a sample implementation:
function Queue() {
var oldestRequest,
newestRequest,
map = {};
this.addUser = function(userID) {
var newRequest = { userID: userID };
map[userID] = newRequest;
// Set this as the oldest request if it is the first request
if (!oldestRequest) {
oldestRequest = newRequest;
}
// If this isn't the first request, add it to the end of the list
if (newestRequest) {
newestRequest.next = newRequest;
newRequest.previous = newestRequest;
}
newestRequest = newRequest;
};
this.nextUser = function() {
// If we don't have any requests, undefined is returned
if (oldestRequest) {
var request = oldestRequest;
oldestRequest = request.next;
delete map[request.userID];
// Make sure we don't hang on to references to users
// that are out of the queue
if (oldestRequest) {
delete oldestRequest.previous;
}
// This is the last request in the queue so "empty" it
if (request === newestRequest) {
newestRequest = undefined;
}
return request;
}
};
this.removeUser = function(userID) {
var request = map[userID];
delete map[userID];
if (request.previous) {
request.previous.next = request.next;
}
if (request.next) {
request.next.previous = request.previous;
}
};
return this;
}
You can use a map together with a queue to provide constant time access. Below is the implementation in TypeScript 4.2. Map is used instead of Object to provide better performance in addition and removal of values.
// TypeScript typing
export type KeyValuePair<K, V> = [ K, V ]
interface ValueData<V> {
value: V
refCount: number
}
// Public classes
export class MapQueue<K, V> {
readonly #queue: Array<KeyValuePair<K, V>>
readonly #map: Map<K, ValueData<V>>
constructor () {
this.#queue = []
this.#map = new Map()
}
get length (): number {
return this.#queue.length
}
unshiftOne (pair: KeyValuePair<K, V>): number {
const [key, value] = pair
const valueData = this.#map.get(key)
if (valueData !== undefined) {
if (valueData.value !== value) {
throw new Error(`Key ${String(key)} with different value already exists`)
}
valueData.refCount++
} else {
this.#map.set(key, {
value,
refCount: 1
})
}
return this.#queue.unshift(pair)
}
pop (): KeyValuePair<K, V> | undefined {
const result = this.#queue.pop()
if (result !== undefined) {
const valueData = this.#map.get(result[0])
if (valueData !== undefined) {
valueData.refCount--
if (valueData.refCount === 0) {
this.#map.delete(result[0])
}
}
}
return result
}
get (key: K): V | undefined {
return this.#map.get(key)?.value
}
}