NodeJS: Mongoose jak zapobiegać dodawania identyfikatora do zagnieżdżonego dokumentu?

Opublikowano: - tagi:

Zagnieżdżone dokumenty

Mongoose pozwala na dodawanie zagnieżdżonych dokumentów do kolekcji:

import { model, Schema } from 'mongoose';

export interface Tag {
    name: string;
    value: string;
}

export interface Product {
    title: string;
    description: string;
    tags: Tag[];
}

const ProductSchema = new Schema<Product>({
    title: { type: String, required: true },
    description: { type: String, required: true },
    tags: { type: [{
            name: { type: String, required: true },
            value: { type: String, required: true },
        }],
        default: () => []
    }
}, { versionKey: false });

export const ProductModel = model('Product', ProductSchema);

Kiedy dodamy do kolekcji nowy rekord:

const productToAdd: Product = {
    title: 'Some product',
    description: 'Lorem ipsum',
    tags: [
        { name: 'Tag 1', tag: 'tag1' },
        { name: 'Tag 2', tag: 'tag2' },
    ]
};

const addedProduct: Product = await ProductModel.create(productToAdd);
console.log(addedProduct);

Powstanie coś takiego:

{
    _id: '5c2dcec42161327d7bf6bd63',
    title: 'Some product',
    description: 'Lorem ipsum',
    tags: [
        { 
            _id: '5caa542e2161327d7bf6c086'  
            name: 'Tag 1',
            tag: 'tag1' 
        },
        { 
            _id: '5cb183c82161327d7bf6c097',
            name: 'Tag 2', 
            tag: 'tag2'
        },
    ]
};

Po utworzeniu nowego dokumentu do rekordu zostały dodane trzy pola: _id. Jak pozbyć się identyfikatorów w zagnieżdżonym dokumencie (tags), jeśli ich nie potrzebujemy?

Zapobieganie dodawania identyfikatorów

Rozwiązanie jest banalne. Wróćmy do definicji naszego modelu. Skupmy się problematycznym tags:

tags: { 
    type: [{
        _id: false, // Ustawiamy flagę
        name: { type: String, required: true },
        value: { type: String, required: true },
    }],
    default: () => []
}

Jak widać, wystarczy dodać pole: _id: false, aby pozbyć się niechcianych identyfikatorów!


React: Jak przekazać komponent do innego komponentu?

Opublikowano: - tagi:

Jak przekazać komponent do innego komponentu?

React pozwala na przekazywanie komponentu lub komponentów do już istniejącego.

Żeby przekazać komponent do innego komponentu, korzystamy ze specjalnej właściwości o nazwie children. Wykorzystujemy ją w komponencie nadrzędnym:

function Component1({ label, children }) {
    return (
        <div>
            <h2>{label}</h2>
            {children}
        </div>
    );
}

function Component2({ text }) {
    return <p>{text}</p>;
}

Następnie za pomocą składni JSX piszemy:

<Component1 label="Section 1">
    <Component2 text="Lorem ipsum..." />
</Component1>

Wyrenderuje:

<div>
    <h2>Section 1</h2>
    <p>Lorem ipsum...</p>
</div>

Możemy przekazać więcej niż jeden komponent:

<Component1 label="Section 1">
    <Component2 text="Lorem ipsum..." />
    <Component2 text="Etiam vel varius mi" />
    <Component2 text="Nullam metus orci" />
</Component1>

React: Komponenty podstawy

Opublikowano: - tagi:

Jak stworzyć własny komponent?

Żeby stworzyć własny komponent, wystarczy napisać:

function Header() {
	return <h2>Some header</h2>
}

Jak widać, użyliśmy tutaj zwykłej funkcji i to wystarczy. Komponenty w React można stworzyć za pomocą funkcji i klas. W tym wpisie przedstawiamy przykłady komponentów stworzonych za pomocą funkcji.

Żeby go użyć, piszemy:

function App() {
	return (
		<div>
			<Header />
		</div>
	);
}

We fragmentach kodu korzystamy z JSX

Jak wyświetlić dane w komponencie?

Jeśli chcemy wyświetlić jakieś dane w komponencie, musimy użyć nawiasów klamrowych: { }

function Header() {
    const title = 'Some header';
    return <h2>{title}</h2>
}

Jak przekazać dane do komponentu?

Żeby przekazać dane do komponentu, korzystamy z obiektu, który nazywa się: props:

function Header(props) {
    return <h2>{props.title}</h2>
}

albo krócej:

function Header({ title }) {
    return <h2>{title}</h2>
}

Następnie:

function App() {
	return (
		<div>
			<Header title="My header" />
		</div>
	);
}

Jeśli wartość, którą chcemy przekazać, przechowujemy w zmiennej, to musimy użyć nawiasów klamrowych:

function App() {
    const myHeader = 'My header';

    return (
        <div>
            <Header title={myHeader} />
        </div>
    );
}

RxJS: Operator combineLatest

Opublikowano: - tagi:

Do czego służy combineLatest?

Operator combineLatest przyjmuje jako parametr listę obiektów typu Observable. Jako wynik zwraca wartości wysłane przez te obiekty.

Żeby combineLatest zwrócił wynik, musi zostać spełniony jeden warunek: wszystkie przekazane do operatora obiekty Observable muszą wysłać swoje dane. Na przykład: przekazujemy do combineLatest dwa strumienie danych. Jeden strumień wysłał dane, ale drugi jeszcze nie. W tym przypadku combineLatest nie zwróci żadnych danych (patrz przykład 1).

Dodatkowo combineLatest zwróci kolejny raz dane, jeśli któryś ze strumieni także wysłał nową porcję danych (patrzy przykład 2). W tym przypadku wystarczy, że tylko jeden obiekt Observable wyemituje dane.

Przykłady użycia combineLatest

Przykład 1

import { of, combineLatest} from 'rxjs';
import { delay } from 'rxjs/operators';

combineLatest([
    of(1),
    of(2).pipe(delay(1000)),
    of(3).pipe(delay(2000)),
]).subscribe(console.log); // [1, 2, 3]

Jako wynik zwróci: [1, 2, 3] ale po 3 sekundach. Zauważ, że pierwszy strumień zwraca dane od razu, drugi po sekundzie, w końcu trzeci po dwóch sekundach. combineLatest wysyła dane, gdy wszystkie przekazane do niego obiekty Observable wyślą swoje dane.

Przykład 2

W HTML dodaj dwa input'y:

<input type="text" id="field1" />
<input type="text" id="field2" />

Kod:

import { fromEvent, combineLatest} from 'rxjs';
import { map } from 'rxjs/operators';

function createKeyupListener(inputId) {
    return fromEvent(document.getElementById(inputId), 'keyup').pipe(
        map((event) => event.target.value)
    );
}
const field1$ = createKeyupListener('field1');
const field2$ = createKeyupListener('field2');

combineLatest([
    field1$,
    field2$
]).pipe(
    map(([a, b]) => {
        return parseFloat(a) + parseFloat(b)
    })
).subscribe(console.log);

Gdy wpiszemy w jedno pole wartość nic się nie stanie. Wprowadzając dane do drugiego pola combineLatest wyemituje sygnał z przetworzonymi danymi. Jeśli ponownie wprowadzisz dane do któregoś pola to combineLatest od razu wyśle nowy wynik. Czyli tylko za pierwszym razem combineLatest czeka, aż wszystkie przekazane do niego strumienie wyślą dane. Później wystarczy, że nowe dane zostaną wyemitowane przez jeden ze strumieni.


React: Czym jest JSX?

Opublikowano: - tagi:

Do czego służy JSX?

React pozwala na tworzenie widoku komponentu za pomocą specjalnej składni o nazwie: JSX. JSX to po prostu rozszerzenie JavaScript dzięki, któremu możemy umieszczać znaczniki HTML'owe w kodzie.

Najprostszy przykład:

const header = <h2>Hello React!</h2>;

Przykład z przekazaniem wartości:

function createHeaderHello = (name) => {
  return <h2>Hello {name}!</h2>;
}

createHeaderHello('Magda'); // <h2>Hello Magda!</h2>

Różnice między JSX a HTML

Używając JSX należy mieć świadomość, że istnieją pewne różnice między JSX a zwykłym HTML.

Na przykład w zwykłym HTML chcemy nadać klasę CSS danemu elementowi:

<div class="some-class">Div element</div>

W JSX to samo zapiszemy tak:

const element = <div className="some-class">Div element</div> 

Tutaj użyliśmy className. Jest tak, ponieważ JSX używa składni camelCase.

JSX a wstrzyknięcie kodu z zewnątrz

Wszystko, co pochodzi od użytkownika a my to wyświetlamy za pomocą JSX jak na przykład:

const element = <div>{data}</div> 

Można uznać za bezpieczną operację. Autorzy Reacta zapewniają, że dzięki JSX unikniemy ataku typu wstrzyknięcia złośliwego kodu na naszą stronę.