ToCode
Open in Telegram
ืืืคืื ืงืฆืจืื ืืืชืื ืชืื ืืืช ืื ืื ืคืจืง
Show more1 417
Subscribers
-224 hours
-37 days
-630 days
Posts Archive
1 417
ืืืืืืืืช ืฉื ืจืืืงื ืืืืชื ืขืืื ืื ืืจืืื ืืื ืืืฉืชืืฉ ื useDeferredValue ืื ืืขืืืื ืขื ืืงืฉืืช ืจืฉืช, ืืื ืคื ืฆืจืื ืืืืืืฉ ืฉืื ืื ืื ืื ืื ืืืืกืช ืืช ืืืืช ืืงืจืืืืช ืืฉืจืช ืืื ืจืง ืืช ืขืืืื ื ืืืฉืง ืืืฉืชืืฉ ืืืื ืื ืืกืคืืง ืืืื ืืื ืืืืกืช ืงืื ืชืงืฉืืจืช.
1 417
ืืคืงืืืืช debounce ื deferred ืืจืืืงื
ืืืื ื ืืืจ ืขื ืฉื ื ืื ืื ืื ืื ืคืืคืืืจืืื ืืืืฉืืื ืจืืืงื ืขื ืกืื ืื ืจืฉืืืืช ืื ืืื ืื ืืืืื ืืื ืืื ืืืชื ื ืฉืชืืฉ ืืื ืืื (ืื ืืฉื ืืื ืืื).
ืขืืืื ืขื Debounce ืืจืืืงื
ืืฉืืฉ ืื ืจืฉืืื ืืืืื ืฉื ืคืจืืืื ืืื ื ืจืืฆื ืืกื ื ืืืชื ืืกืื ืื ืขืฆืื ืขืืื ืืืืืช ืคืขืืื ืืืื. ืืืชืจ ืืื, ืื ืืกืื ืื ืขืฆืื ืืืื ืืืฉื ืืฉืจืช ืืคืขืืช ืืืชืจ ืืื ืคืขืืืืช ืกืื ืื ืืืืื ืืืฆืืจ ืขืืืก ืขื ืืฉืจืช. ืืื ืื ืื ื ืืฉืชืืฉืื ืืื ืื ืื debounce ืืื ืืืืฆื ืืช ืืงืจืืืืช, ืืืืืจ ื ืจืฆื ืืฉืืื ืืช ืืงืฉืช ืืกืื ืื ืืฉืจืช ืจืง ืืืจื ืฉืืืฉืชืืฉ ืกืืื ืจืฆืฃ ืืงืืืืช. ืืืจื ืืื debounce ืืืืืฉ ืขื ืืื ืืืชื ื ืฉื ืืฆื ืฉื ืื ืื ืฉื ืื ืืจืืข ืืฉืื ืื ืืืืจืื ืืขื ืืจืืข ืฉืืืืช ืฉืืืืื ืืช ืืืืขืช ืืืืคืืฉ ืืฉืจืช. ืื ืืืืื ืืืื ืืื ืืืฉืชืืฉ ืืงืืื ืืฉืื ื ืืกืฃ ืื ื ืชืืื ืืช ืืกืคืืจื ืืืืฉ.
ืืคืื ืงืฆืื
useDebounce ืืชืื ืืืืกืฃ useHooks ืืืืืฉืช ืื:
export function useDebounce(value, delay) {
const [debouncedValue, setDebouncedValue] = React.useState(value);
React.useEffect(() => {
const handler = setTimeout(() => {
setDebouncedValue(value);
}, delay);
return () => {
clearTimeout(handler);
};
}, [value, delay]);
return debouncedValue;
}
ืืื ืืืงืืช ืขืจื ืฉืืื ืืจืื ืืฉืชื ื ืกืืืื ืืืฉืื ืืืกืคืจ ืืืื ืฉื ืืืช ืืืืชื ื. ืืื ืืืืืจื ืืฉืชื ื ืกืืืื ืคื ืืื ื ืืกืฃ ืฉืืชืขืืื ืจืง ืืืจื ืฉืืขืจื ืืืงืืจื ืื ืืฉืชื ื ืืืฉื delay ืืืื-ืฉื ืืืช. ืืขืืจืช ืืคืงื ืืคืื ืงืฆืื ืืืืืจื timeout ืืืืคืกืช ืืช ืืฉืขืื ืื ืคืขื ืฉ value ืืฉืชื ื.
ืื ื ืืฉืชืืฉ ืืคืื ืงืฆืื ืืืืคื ืืื:
function TextWithDebounce() {
const [text, setText] = useState('');
const debouncedText = useDebounce(text, 1000);
return (
<>
<input type="text" value={text} onChange={e => setText(e.target.value)} />
<p>Character Count: {debouncedText.length}</p>
</>
)
}
ืืงืืืคืื ื ืื ืชืฆืื ืชืืืช ืืงืกื ืืจืง ืืืจื ืฉืืฉืชืืฉ ืืคืกืืง ืืขืืื ืืช ืืืงืกื ืืชืืื ืืื ืชืฆืื ืืช ืืกืคืจ ืืชืืืื ืฉืืืงืืื.
ืขืืืื ืขื useDeferredValue ืืจืืืงื
ืืคืื ืงืฆืื useDeferredValue ืืื ืืืจ ืืืง ืืืื ื ืืจืืืงื ืืืืจืชื ืืืืฆื ืืช ืืืฉืง ืืืฉืชืืฉ ืืืืฆืขืืช ืืจืฆืช ืงืื ืจืืืงื ืืจืงืข. ืื ื ืืกืืืจ:
1. ืืฉืจืืืงื ืืืื ืฉืื ืื ืืืฉืชื ื ืกืืืื ืืื ืืื ืืจืืฅ ืืช ืคืื ืงืฆืืืช ืืงืืืคืื ื ืื ืื ื ืืฆื ืืืชื ืืฉืชื ื ืกืืืื, ืืืขืงืืืชืื ืืืฉืื ืืืฉื ืืช ืื ืืงืืืคืื ื ืืืช ืฉืืชืืื, ืืื ืืื ืืช ืืช ื Virtual DOM ืืืืฉ ืฉืืืฉืคืข ืืืฉืื ืื.
2. ืืจืฆืช ืชืืืื ืืืืฉืื ืขืฉืืื ืืืืืช ืืืืืช, ืืืืื ืืื ืืืฉืง ืืืฉืชืืฉ ืื ืืขืืืื. ืืืชืจ ืืื, ืืืืื ืชืืืื ืืืืฉืื ืืืืืื ืืงืจืืช ืืืจืืขื UI ื ืืกืคืื ืฉืืืืคืื ืืืืืืจ ืื ืืืคืืคื ืขืกืืง ืืืืฉืื ื Virtual DOM ืฉื ืืฉืื ืื ืืงืืื.
ืคืื ืงืฆืืืช useDeferredValue ืืฆืืขื ืคืชื ืืืืื ืืืขืื ืื - ืืื ืืืคืฉืจืช ืื ื ืืืืฉืื ืืืฆืื ืืช ืืขืจื ืืืฉื ืืืืฉื ืืช ื Virtual DOM ืืืืฉ ืืจืงืข. ืื ืืืื ืืืจืืขื UI ื ืืกืคืื ืฉืืฉื ื ืืช ืืกืืืื ืจืืืงื ืืืื ืืขืฆืืจ ืืช ืืืืฉืื ืืจืงืข ืืืืชืืื ืืืฉืื ืืืืฉ ืขื ืืขืจื ืืืืฉ, ืื ืืืช ืืื ืืคืืืข ืืืืืข ืฉืืืฆื ืขื ืืืกื. ืจืง ืืืจื ืฉืืืืฉืื ืืจืงืข ืืกืชืืื ืจืืืงื ืืืืืฃ ืืช ืืชืืื ืฉืขื ืืืกื "ืืืื ืืืช" ืืื ืืคืืืข ืืืืืืช ืืืฉืชืืฉ.
ื ืชืืื ื ืืืืืืช ืืงืื ืืืื ืืืฃ ืืชืืขืื ืฉื ืืคืื ืงืฆืื:
import { useState, useDeferredValue } from 'react';
import SlowList from './SlowList.js';
export default function App() {
const [text, setText] = useState('');
const deferredText = useDeferredValue(text);
return (
<>
<input value={text} onChange={e => setText(e.target.value)} />
<SlowList text={deferredText} />
</>
);
}
ืืื ืื ืฉืืืงื ืืจืื ืืื ืืื ืืช ืืช SlowList ืขืืืจ ืืงืกื ืืกืืื, ืืฉืืืืฉ ื deferredValue ืืืคืฉืจ ืืจืืืงื ืืืืื ืืฉืื ืืืื ื text ืืื ืืฉืื ืงืืจืื ืืืืจืืฅ ืืช ืืืืฉืื ืฉื SlowList ืืจืงืข. ืื ืืืืฉืื ืืกืชืืื ื text ืื ืืฉืชื ื ืื ืืืื ืืืช ืืขืจื ืฉื deferredText ืืืืืฃ ืืขืจื ืืืืฉ ืฉื text ืืจืืืงื ืืฉืชืืฉ ื Virtual DOM ืฉืืื ืืืจ ืืืฉื. ืื text ืืฉืชื ื ืืืืฆืข ืืืืฉืื ืื ืจืืืงื ืคืฉืื ืืขืฆืืจ ืืช ืืืืฉืื ืืงืืื ืืืชืืื ืืืฉื ืืืืฉ ืืช SlowList ืขื ืืืงืกื ืืืืฉ.
ื .ื. ืืฉืืื ืฉืืืืื ืื ืชืขืืื SlowList ืืืื ืืืืืช ืืืืืจ ืขื memo ืื ืืฉ text ืืฉืชื ื ืจืืืงื ืื ืกื ืืืฉื ืืืืฉ ืืช App ืืืื memo ืื ืื deferredText ืื ืืฉืชื ื ืขืืืื ืจืืืงื ืืฆืืจื ืืืฉื ืืืืฉ ืืช SlowList.1 417
ืืฆืขื ืืคืจืืืคื - ืืื ืืฉืืืจ ืืช ืืงืื
ืืื ืืงืฉืืื ืฉื ืืชืื ืชืื, ืืืืืื ืืขืืื ืฉื ืืืืืช ืืืืข ืืื ืื ืืืืฅ, ืืื ืืจืืืช ืืื ืืงืื ืฉืื ืืืจื ืืืขืื ืืืชื ืืืืช ืืืขืจืืช. ืืื ืฉืืกืชืชืจ ืืืืื ืืคืืฆ'ืจ ืืืฉ ืฉื ืจืฆื ืืืืกืืฃ ืืื ืคืชืืื ืืืคืืข ืืืืื ื ื ืฉืื "ืืื ืืื ืื ืขืื ืขื ืขืืฉืื?".
ืื ืื ื ืืฆืขื ืืคืขื ืืืื ืฉืืชื ืืงืฉืงืฉืื ืขื ืงืืื ืื ืืืจ ืืืจ, ืื ืืืื ืืื:
> Let's play a game - the code below has a hidden bug, but it will be triggered if we add a specific feature. What new feature will break this code?
ืื ื ื ืชืชื ืื ืืฉืืื ืืืืืื ืืช ืืงืื ืจืืืงื ืืื ืืืื ืงืืข ืืื ืืคืืฆ'ืจ ืฉืืื ืฆืจืื ืืฉืืื ืืจืืืช ืืช ืืืื:
function ColorPalette({ start }: {
start: ColorInput,
}) {
const [deletedBoxes, setDeletedBoxes] = useState(new Set());
const removeBox = useCallback((e: React.MouseEvent) => {
console.log(\deleted boxes = ${deletedBoxes.size}\);
const id = (e.target as HTMLDivElement).dataset.id;
deletedBoxes.add(Number(id));
setDeletedBoxes(new Set(deletedBoxes));
}, [deletedBoxes, setDeletedBoxes]);
const colors = [];
for (let i=-360; i < 360; i++) {
if (deletedBoxes.has(i)) continue;
colors.push(
<ColorBox
key={i}
start={start}
spin={i}
onClick={removeBox}
id={i}
/>
);
}
return colors;
}
(ืืื ืื ืจืื ืฉืืคืฉืจ ืืืืจืื ืืช ืืชืืืืืช Let's play a game, ืืื ืื ื ืืืฆื ืฉืืชืฉืืืืช ืฉื AI ืืืชืจ ื ืืืืืช ืืฉืืื ืืืฉื ืฉืืื ืืืฉืืง).1 417
ืืื ืืืืืืืืจ ืื ืืจืืฅ?
ืืื ืืขื ืืื ืืื ืื ืื ืืืืืืืืจืื ืฉื next.js ืืืคืฉืจ ืืชืืงืคืื ืืืื ืขื ืืืืืืืืจ ืืืืฆืขืืช ืืืจืงืช ืืืชืจืช ืืืืืืช ืืืงืฉื. ืื ื ืืื ืก ืืคืจืืื ืืืื ืืื ืืื ืื ืฉืืื ืืฉืื ืื ืืกืืคืืจ ืื ืงืืืช ืืื ืฉื ืืืืืช ืืืืข. ืืืืฉืืืื ืจืืื ืื ืื ืื ื ืืืื ืืืฉืชืืฉืื ืืืกืืืช ืืืฉื ืื ืชืืืื ืืกืืืืื ืืชืืฆืข ืืืืืืืืจ, ืืคื ื ืฉืืืงืฉื ืืืืขื ืืงืื ืฉืืืจืื ืขื ืืืืคืื ืื. ืืฉ ืคื ืจืืืื ืืจืืืืงืืื ืืช ืฉื ืืคืจืื ืืื ืืงืื "ืฉืื ืื ืืืฉื" ืืงืื "ืฉืืืฆืข ืืช ืืคืขืืื". ืืืืืื ืืืืจืื ืฉื auth0-next ืืฆืืชื ืืช ืืืืืง ืืื:
import { withMiddlewareAuthRequired } from "@auth0/nextjs-auth0/edge";
export default withMiddlewareAuthRequired();
export const config = {
matcher: ["/protected", "/admin"],
};
ืืงืื ืืืืืจ ืฉืืืฉื ืื ืชืืื protected ื admin ืืืชืจืช ืจืง ืืืฉืชืืฉืื ืืืืืชืื. ืืชื ืจืืืื ืืช ืืืขืื ื ืืื? ืื ืืืืืืืืจ ืื ืจืฅ ืืืืฉื ืคืชืืื ืืืืื.
ื ืฉืืื ืืช ืื ืืขืืงืจืื "ืืืืงืื ืฆืืื ืืคืขืืื ืืืกืืื ืช" ืฉื ืคืืชืื ืงืื ืืืืืื. ืืขืืืื ื ืืื ื ืื ืื ื ืจืืฆืื ืืืืืง ืืจืฉืืืช ืืชืื ืืฃ ื admin, ืืืคืืื ืืชืื ืืคืื ืงืฆืื ืฉืืืฉืืช ืืืืข ืฉื ืื ืื ืืืกืืก ืื ืชืื ืื. ืฉืืื ืื ืืืืืืฉ ืืืืืื ืืื ืืชืื ืืืชื ืืืจืื:
export const getUserProfileData = async (): Promise<Claims> => {
const session = await getSession();
if (!session) {
throw new Error(\Requires authentication\);
}
const { user } = session;
return user;
};
ืคืื ืงืฆืื ืืืืช ืื ืชืืคืฉืจ ืืืฉืื ื ืชืื ืื ืจืืืฉืื, ืืคืืื ืื ืื ืืงืื ืฉืืคื ืื ืืืื. ืืื ืืขืฆืื ืืืงืืช ืืช ื ืชืื ื ืืืฉืชืืฉ ืืืืืืืช ืฉืืืฉืชืืฉ ืืืืืจ. ืืืขืจืืช ืขื ืื ืื ืื ืืจืฉืืืช ืคืื ืงืฆืื ืื ืชืืื ืื ืืืืื ืฉืืืฉืชืืฉ ืฉืืืืืจ ืืฉ ืืจืฉืืืช ืืืฆืข ืืช ืืคืขืืื ืฉืืื ืจืืฆื ืืืฆืข, ืืจืง ืื ืชืจืืฅ ืืช ืืงืื ืืืกืืื.
ืงืื ืืืืืื ืื ืื ืื ืฉืืืฉืื ืืคื ืื ืืืง ืืจืฉืืืช - ืืื ืืืืง ืืจืฉืืืช ืฆืืื ืืืืืืง ืืคื ื ืืคืขืืื ืืืกืืื ืช, ืืื ืฉืื ืืคืฉืจ ืืืื "ืืืื" ืขื ืืืืงืช ืืืจืฉืืืช ืืืืืืข ืจืง ืืงืื ืืจืืืฉ.1 417
ืืืค JavaScript - ืฉืืืืฉ ื matchMedia ืืืงืื resize
ืคืงืืืช matchMedia ืืื ืืจืืง ืืืื ืฉืืืคืฉืจ ืื ื ืืงืื ืืืจืืข ืื ืคืขื ืฉ"ืืชืืืช ืืืกื ื Media Query" ืืกืืื ืืฉืชื ื. ืื ืื ืื ืื ืืจืื ืืืชืจ ืืขืื ืืืืจืืขื resize ืื ืจืื ืืืื ืื ืฉืืขื ืืื ืืืชื ื ืื ืื ืฉืืฉืชืืฉ ืฉืื ื ืืช ืืืื ืืืืื ืืื ืฉืืืื ืืืืื ื ืืื ืืกืคืืง ืงืื ืืื ืืืชืืืก ืืืื ืืื ืืืืคืื, ืื ืืกืคืืง ืืืื ืืื ืืืฆืื ืขืืื ืืืชืจ ืืืืข. ืืืช ืืขืฆื ืืืจืกืช ื JavaScript ืฉื Media Queries ื CSS.
ืื ื ืืืืื ืงืฆืจื ื Hook ืจืืืงืื ืฉืืืืง ืื ืื ืื ื ืขื ืืืฉืืจ ืืืืืื:
const MOBILE_BREAKPOINT = 768
export function useIsMobile() {
const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined)
React.useEffect(() => {
const mql = window.matchMedia(\(max-width: ${MOBILE_BREAKPOINT - 1}px)\)
const onChange = () => {
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
}
mql.addEventListener("change", onChange)
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
return () => mql.removeEventListener("change", onChange)
}, [])
return !!isMobile
}1 417
ืืืื ืฉืงืืคืื
ืื ืืขืชืื ืฉืื ื ืืื ืขืืืจื AI ืืืชืืืช ืงืื ืื ืืืื ืฉื ืืฉืื ืฉืื ืขื ืฉืคืืช ืืคืืชืื ืืืกืคืจืืืช ืืื ืื ืื ื ืืฉืชืืฉืื. ืื ื ืืื ืืืจืื ืฉืืืืชื ืืืฉืืงืื ืขื AI ืืฉืืืข ืืืืจืื:
1. ืืืื ืงื ืื ืืืชืื ืืฉืืง ืกื ืืืง, ืืืื ืงืฉื ืืืฉืชืืฉ ื ืืื ืืกืคืจืืืช ื npm. ืื ืงืืจื ืื ืืฉืืง ืกื ืืืง ืืฉืชืืฉ ืจืง ืืืืืืืช ืฉื ืืืคืืคื ืืืืืจ ืืืืข ืฉืืื ืืชืืื ืขืืื, ืืืืื ืกืคืจืืืช ื npm ืืฉื ืืช ืืช ืืืืฉืง ืื ืฉืืืฉื ืืืืฉืื ืืืื ืืฉ ืืืชืจ ืืื ืงืื ืืงืกื.
2. ืืืื ืงื ืื ืืืชืื ืฉืืืืชืช SQL, ืืจืื ืืืชืจ ืงืฉื ืืืชืื ืงืื ORM.
3. ืืืื ืงื ืื ืืืชืื ืชืื ืืช SAM ืืืจืืืืงืืืจืช Serverless ืขื AWS, ืืจืื ืืืชืจ ืงืฉื ืื ืืชืงื ืกืงืจืืคื ืืชืงื ื ืืฉืจืช VPC.
4. ืืืื ืงื ืื ืืืชืื ืขืืื ืืืฉ ืืืชืจ, ืืจืื ืืืชืจ ืงืฉื ืืฉืืขืืื ืฆืจืื ืืืฉืชืืฉ ืืงืืืคืื ื ืืืช ืงืืืืืช ืืืืขืจืืช ืฉืืืื ืื ืืชืืขืืืช ืืกืคืืง ืืื.
5. ืืืื ืงื ืื ืืืชืื ืืืืงืช End To End ืืคื ืจืฉืืืช ืชืจืืืฉืื ืฉืื ื ืืชืืจ, ืืจืื ืืืชืจ ืงืฉื ืืืงืื ืชืฉืชืืช ืืืืืงืืช ืืืืื ืืืืืืื ืืืื Mock-ืื ืืขืฉืืช ืืืื ืฆืจืื ืืืจืื ืืืจืช ืืช ืืงืื ืืกืคืฆืืคื ืฉืื ืืื ืฉืืืื ืงื ืืืชืื ืืืชื.
ืื ืฉืืฉืืชืฃ ืืื ืืืงืจืื ืืื, ืืืขืืืื ืขื AI ืืืืคื ืืืื ืืื ืืงื ืฉืืื ืืกืคืฆืืคื ืืืืื - ืืื ืฉืืืืืจ ืืืงืืช "ืงืื ืืกืคืจ ืืืืื" ืืืืืืืง ืืืชื ืืคืจืืืงื ืชืื ืืืฆืืข ืืชืืืืช ื ืืจืฉืืช ืืืจืื ืืขืืื ืืืคืชืืขื ืืืืื. ืืจืืข ืฉืื ืื ื ืืืืขืื ื Refactoring ืื ืืงืืืช ืืืืืืช ืืขืกืง ืืกืชืื. ืื ืืืืจ ืฉืื ืื ืื ื ืจืืฆืื ืืืจืืืื ื AI ืืืื ืืืคืฉ ืืช ืืืงืืืืช ืืื ืืืื ืืงืื ืืงืกื ืงืื (ืฆืจืื ืคืืืช ืืืงื ืื ืืงืื ืืื ืืคืชืืจ ืืช ืืืขืื) ืืืืฉืืขืืช ืฉื ืืืืงื ืื ืืฆืืื. ืื SQL ืื ืืฆืืื ืื ืืื ืฉืืชืืชื ืืช ืืฉืืืืชื ืืื ืืื ืืืืืช ื DB, ื ORM ืื ืืกืืื ืื ืืืืจืืช ืืงืฉืจืื ืืื ืืืืืืื ืืืืงืืืช ืืงืืืฅ ื ืคืจื ืื ืืื ืงืืฆืื ืื ืฉืืืื ืืื ืงืืฆืื ื DB.
ืจืืฆืื ืืืจืืืื ื AI? ื ืกื ืืืืื ืืช ืืคืจืืืงื ืฉืืื ืืืืืื ืืืื ืฉืงืืคืื ืืกืื ืืจืืืื. ืืืกืืจืงืฆืืืช ืืชืืืืืืช ืืกืคืฆืืคืืืช ืืืขืจืืช ืฉืื ื ืืืฆืจืืช ืขืืฉืื ืขืืืช ืืืฉื ืืืืื ืื ืฉืืืืช ืืช ืืืืืฅ.
1 417
ืชืื ืืช ืืคืืชืื Chat Bot ื Next.JS
ืื ืืฉื ื ืืื ืืฉืืชื ืฉืืื ืงืฉื ืขื ืื ืืกืคืจืืืช ืฉืืฉืชื ืืช ืื ืืืื ืืขืืื ื Full Stack, ื AI ืื ืืจืื ืืืชืจ ืงืฉื. ืืืื ืืืื ืื ืื ืืฆืืืืื ืืื ืืช ืืฉืืง ืกื ืืืง ืืคืืืช ืืืงื, ืืื ืจืง ื ื ืกื ืืฉืื ืฉืฆืจืื ืกืคืจืืืช ื npm ืืืื ืืืื ืืืืืื ืืืืจืกืืืช. ืืื ืืื ืื ืขืืืื ืืฉ ืืืื ืืืจืื ื npm ืฉืืืืืื ืืืกืื ืื ื ืืื ืคืืชืื ืืืืืื. ืืืืืื ืฉืื ื ืืืื ืืื ืกืคืจืืืช ื ai ืฉื Vercel.
ืื ืืฉ ืืื
ืืจืกื ืคืืชืื ืืืกืฃ ืกืคืจืืืช ืฉืืืืจืืช ืืื AI Bots ืืืืฉืง ืืฉืชืืฉ, ืื ืฉืืฆื ืืื ืชืืืื ืืืชืื ืืช ืืืืฉืง ืืื ืืจื ืฉืชืจืฆื ืืื ืืฆื ืฉื ื ืชืงืืื ืืืฉื ืืื ืืคืื ืืงืื ืืกืื ืืจืืืื ืฉื ืืืฉืงื AI. ืืืืืื ืฉื ืฆ'ื ืืื ืื ืืืืจ ืฉื ืงืื:
1. ืืืฉืง ืืืื ืืฉืืืืช ืืืืขื ื AI Chat Bot.
2. ืืืืขื ืฉืชืืฉืื ืืืืฉืง ืืืืื ืชืืื ืืืืืจ ืืชืืจ ืืจื ืฉื ืชืืืื, ืืื ืชืืฆื ืืืจ ืืืชืจ ืืืฉืชืืฉืื.
3. ืฉืืืืฉ ืืืืื ืืืืฉืง ืกืื ืืจืื ืืืืืขืืช ืฉื ืืฆืจื ืขื ืืื ืืืื.
4. ืืชืืืช ืืืืขืืช ืืกืืืื ืืื ืืืืื ืฉืืงืืืื ืืช ืืืืืข ืฉืจืฆืื ื ืืืคืืจืื ืฉืจืฆืื ื.
ืืืื ื ืจืื ืืช ืืชืื ืืช ืืคืืชืื Chat Bot ืืกืืกื ืืืกืืฃ ืงืืฉืืจ ืืชืืขืื ืืื ืฉืชืืืื ืืืืฉืื ืืฉื.
ืฆ'ื ืืื ืืกืืกื ื Next.JS
ืืฉืืื ืืื ืืช Chat Bot ืืกืืกื ื Next.JS ืขื ืืืืืื ืฉื ืืจืกื ืชืืืื ื ืชืงืื ืืช ืืืืืื ืขื:
$ npm add ai ai-sdk/react
ืืืืืจ ืืื ื ืืกืืฃ ืกืคืง AI ืฉืื ืืืืื ืืขืืืื ืขื ืฆ'ื ืืื ืืกืืื, ืื ื ืืื ืกืคืงืื ืืืืืื (ืืกืคืืง ืืืืืจ ืืื):
$ npm add @ai-sdk/xai @ai-sdk/openai @ai-sdk/anthropic @ai-sdk/google
ืืืืื ืช ืืงืื ืืฉ ืืคืจืืืงื ืืกื ืืื ืฉื ื ืงืืฆืื. ืงืื ืฆื ืืงืื ืฉืืฆืื ืืืื ืฉืืื:
// file: page.tsx
'use client';
import { useChat } from '@ai-sdk/react';
export default function Page() {
const { messages, input, handleInputChange, handleSubmit } = useChat({});
return (
<>
{messages.map(message => (
<div key={message.id}>
{message.role === 'user' ? 'User: ' : 'AI: '}
{message.content}
</div>
))}
<form onSubmit={handleSubmit}>
<input name="prompt" value={input} onChange={handleInputChange} />
<button type="submit">Submit</button>
</form>
</>
);
}
ืืงืื ืฆื ืฉืจืช ืฉืืืคื ืืคื ืืืช ืืืืงืื, ืืขืืืจ ืืช ืืืืืขื ืืืื ืืฉืืื ืืืืืืจ ืืช ืืฉืืื ืืืจื ืชืืืื:
// src/app/api/chat/route.ts
import { deepseek } from '@ai-sdk/deepseek';
import { streamText } from 'ai';
// Allow streaming responses up to 30 seconds
export const maxDuration = 30;
export async function POST(req: Request) {
const { messages } = await req.json();
const result = streamText({
model: deepseek('deepseek-chat'),
system: 'You are a helpful assistant.',
messages,
});
return result.toDataStreamResponse();
}
ืงืื? ืืื ืื ื ืื ืืื:
https://github.com/ynonp/nextjs-chatbot1 417
ืืืืืง ืืฆืืขืืช
ืืืืืื ืืื ืืฉืืขืืชืืช ืฉืื ืืขืืืื ืขื ืืื AI.
ืืืืืง ืืฆืืขืืช.
ืื ื ืืืชื ืคืจืืืคื, ืืื ืืืืืง ืืฆืืขืืช ืฉืืชืฉืืื ืชืืื ืืื ืฉืจืฆืืชื. ืืืืชื ื ืืชืฉืืื ืืื ืืืง ืืืงืกื, ืืชื ืืืืข ืฉื AI ืืืื ืขื ืชืฉืืื, ืืฉืื ืืืื ืงืฆืช ืืืชืจ ืืืจ ืืื ืฉืืชื ืชืืฆื ืืช ืืชืฉืืื ืืื. ืื ืืืื ืฉืืื ืืืืืช. ืืื ืืื ืฆืืืง ืืืช ืืืฉ ืืืืื.
ืืื ืืฉืืื ืืืขื? ืืฉืืื ืืืขื ืฆืจืื ืืืืืจ, ืืื ืืฉืืื ืฉืืืช ืืืฉื, ืืืชืืื ืืืืชืืื ืื ืืจืืช ืืื ืืืืฉืื ืืื. ืฉืืืช ืืืฉื ืืืืื ืืืฆืืื, ืืืชืืื ืืืืฉ ืขื ืคืจืืืคื ืืืฉ ืื ืืืื ืืขืืื, ืืืืฉืื ืืื? ืขื ืฉืืืขื ื ืขื ืืคื.
ืืื ืื ื ื ืื ืก ืืืืค - ืคืจืืืคื, ืชืฉืืื ืื ืืคืืื, ืชืืงืื. ืคืจืืืคื, ืืืื ืงืื ืืจืืข ืฉืื ืขืืื, ืคืจืืืคื ืืืฉื ืขื ืืืืขืช ืืฉืืืื. ืืฉืื. ืืฉืื.
ืืฉ ืื ืืืจ ืฉืื ืคืขื ืฉืื ื ืืฆืืข ืื ืกืคืจืืืช ืงืื ืคืชืื ืฉืืืืืง ืชืคืชืืจ ืื ืืืื ืืขืื ืกืคืฆืืคืืช ืืื ืืกืชืื ืขืืื ืืืืขืื ืืืกื ื "ืขืืื ืืืชื, ืขื ืฉืื ื ืืืื ืืื ืื ืขืืื ืื ื ืืืจ ืืืชืื ืืื ืืฉืื ืืืชืจ ืืื". ืืืืืช ืืงื ืื ื ืืืื ืืื ืืคืชื ืชืืขืื ืืกืคืืง ืืื ืืกืคืจืืืช ืงืื ืคืชืื ืืืื ืืืืืฆืื ืืกืคืืง ืืืื ืืืื ืืชื ืืืื ืืืฉืชืืฉ ืืื (ืืื ืื ื ืขืืืื ืืชืงืฉืื ืขื ืื). ืืืื ืื ื AI ืฆืจืื ืืชืช ืืื. ืืจืืข ืืจืืฉื ืืื ืฉืืฉ ืืืจืื ืฉืขืืืืื ืืืืกืืื ืืืื ืืื, ืืืฉ ืืืจืื ืฉืื ืขืืืืื ืฉืฉืืืืื ืืืชื ืืฉืขืืช, ืืืจืืจ ืฉืื ืืื ืืคืฉืจ ืืืื ื ืืฉืชืืฉืื ื AI ืจืง ืืืืชื ืืืจืื ืฉืขืืืืื. ืืืื ืืขื ืืื ืืจืืข - ืืื ืืขืชืื ื AI ืืืื ืืช ืืืชืื ืชืื (ืืื ืฉ C ืืืืืฃ ืืช ืืกืืืื, ืืื ืฉืืื ืืืืืืืช ืืื ืืืืืคื ืืคืืืงืฆืืืช ืืกืงืืืค) ืืืืฉืืจื ืจืง ืืจืืืืงืืื, ืื ืืื ืืืฆืจ ืืคืจืืืคืืื?
ืงืฉื ืืืขืช. ืืื ืชืืื ืื ื ืืืืืง ืืฆืืขืืช.
1 417
ืืื ืืืขืืืช ืชืืื ื (ืื ืื ืงืืืฅ ืืืจ) ื Next.JS ื 2025
ืจืืืงื 19 ื next 15 ืขืืืืื ืืื ืืืจืืื ืื ืืื ืืืคืฉืจ ืื ื ืืืชืื ืชืื ืืคืฉืืืื ืืืชืื ืืคืืืงืฆืืืช Full Stack ืืืืืจืืช. ืืื ืืืงืืืืช ืฉืงืืื ืืืคืื ืืืื ืืืจืฆืื ืืื ืืื ืืืคืกืื. ืืืื ื ืจืื ืืื ืขืืืืื ืขื ืืคืกืื ื 2025 ื React ื Next ืืืคืจื ืืื ืืืขืืืช ืชืืื ืืช ืืฉืจืช.
ืงืื ืืืืคืก
ืจืขืืื ืจืืฉืื ืฉืืืืจืื ืืจืืืงื ืื Vercel ืืืืืฆืื ืขืืื ืืื ืฉืื ืืืืืื ืืฉืืืจ ืืช ืืขืจืืื ืืืืืคืก ืืืฉืชื ื State. ืื ืืคืฉืจ ืืขืฉืืช ืืช ืื ืื ืจืืฆืื ืืืืืืฆืื, ืืื ืืืืื ืื ืืืืืืืฆืื ืฉืืื ืงืืจืืช ืจืง ืืฉืืืืฉืื ืืช ืืืืคืก ืืคืฉืจ ืืืืืจ ืืืืื ืฉืืคื ื ืืกืืืื ืืคืฉืื ืืืชืื ืืืคืก ืขื ืฉืืืช ืืฉืืืช, ืืืืืืง ืืช ืืขืจืืื ืืคืื ืงืฆืื ืืจืืืืช ืืืช.
ืงืื ืืืืคืก ืฉืื ื ืจืื ืื:
'use client';
import { useActionState, } from "react"
import { saveImage } from '@/lib/save-image';
export default function Home() {
const [state, formAction, isPending] = useActionState(async (previousState: string, formData: FormData) => {
const file = formData.get('image') as File;
const description = formData.get('description') as string || "Default description";
if (!file || file.size === 0) {
return "No Image Selected"
}
if (!description) {
return "No Description Provided"
}
return await saveImage(file, description);
}, "");
return (
<div>
<p>{state}</p>
<form action={formAction}>
<input type="text" name="description" />
<input type="file" name='image' />
<input type="submit" value="Save Image" />
</form>
</div>
)
}
ืืคืื ืงืฆืื ืฉืื ื ืืขืืืจ ื useActionState ืืืจืืืช ืื ืขื ืืืืืืฆืื, ืื ืขื ืฉืืืืช ืืืืืข ืืฉืจืช ืืื ืขื ืืืืจืช State ืืชืืฆืื ืืชืฉืืืช ืืฉืจืช. ืืคืจืืืจ ืืืืจืื ืืคืื ืงืฆืื ืืื ืืกืืืื ืืจืืฉืื ื, ืืคื ื ืฉืืืืคืก ืืืืฉ, ืืืื ืืืฉืืจ ืืืฉืชื ื ืืืืืจ state. ืืืจื ืืืฉืช ืืืืคืก ืืขืจื ืืืืืจ ืืืคืื ืงืฆืื ืืืื ืก ืืชืื ืืืชื ืืฉืชื ื state.
ืื ืื ืื ืื ืืืคืฉืจ ืื ื ืืืฆืื ืืืืขื ืืืฉืชืืฉืื ืืืจื ืฉืืืืคืก ืืืืฉ, ืื ืืืจืืืช ืฉืืืืืช ืืฆื ืฉืจืช ืื ืฉืืืืืช ืืืืืืฆืื. ืืืืคืก ืืืืืื ืื ื ืืฉืชืืฉ ืืืืจืืืช ืจืืืื ืืคืฉืื ืืฆืื ืืืชื ืขื ืืืกื ืืขื ืืืืคืก. ืืจืื ืืืจ ืืจืืฉืื ืื ืชืืื ืืืจืืืช ืจืืงื ืืืืจื ืฉืืืืฉ ืืืืคืก ืืืคืืข ืฉื ืืืงืกื ืฉืืืืืจ ืืฆื ืืฉืจืช, ืื ืืืืขืืช ืืฉืืืื ืฉืืืืจืืช ืืืคืื ืงืฆืื ืื ืืฉ ืฉืืืืช ืืืืืืฆืื.
ืฆื ืฉืจืช
ืืืืง ืืฉื ื ืฉื ืืงืื ืืื ืืคืื ืงืฆืื saveImage:
'use server';
import { read } from 'node:fs';
import fs from 'node:fs/promises';
export async function saveImage(
image: File,
description: string,
): Promise<string> {
console.log(\Saving image: ${image.name}\);
const buffer = await image.stream().getReader().read();
const data = buffer.value;
if (!data) return "Missing Image File"
const path = \./images/${image.name}\;
const file = await fs.writeFile(path, data);
return 'Image saved OK';
}
ืื ืชืฉืชืืฉื ืื ืืืขืจืืช ืืืืชืืช ืื ืืื ืื ืื ืงื ืืช ืฉื ืืงืืืฅ, ืืื ืื ืืคืฉืจ ืืืืื ืืืื ืืช ืืืื ื:
1. ืืคืื ืงืฆืื ืืืงืืช ืืช ืืงืืืฅ ืืชืืจ ืืืืืงื File, ืฉืื ืืืืืงื ืฉืืฉืืชืฃ ืื ืืฆื ืืงืื ืืื ืืฆื ืฉืจืช.
2. ืืชืื ื File ืืคืฉืจ ืืงืืช stream ืืืจืื ืืืืืข ืืชืืื.
3. ืื ืืื ืืกืืจ ื ืืชืื ืืช ืืืืืข ืืงืืืฅ ืื ืืืืจ ืืืืขื.1 417
ืืืื ืฉื ืืืืืจื ืคืกืคืก ืืช ืืคืืกืงื ืืื ืืฉืืื ืืคืืกื, ืื ืืืกืืฃ ืืืชื-
ืื ืื ืขืืฉืื? ืืื AI ืื ืคื ืืื ืืืืฉืืจ, ืขื ืืืชืจืื ืืช ืืืืกืจืื ืืช ืฉืืื. ืฉืืืืฉ ื ืืื ืืืืื ืืื ืืืืื ืืฉืคืจ ืืช ืืืืจืืช ืืคืืชืื ืฉืืื. ืฉืืืืฉ ืื ื ืืื, ืื ืื ืืืืื ืืืืชื ืจืืข, ืืืื ืืงืืืช ืืืืืจ ืื ื ืืืจ ืฆืืจืืื. ืืืื ืืืืฉื ืฉืืืข ืืื (ื 27.3 ื 20:00) ืขืจื ืืืืืื-ืืืื ืืืืื ืืืชื ืืืืจ ืืืชื ืืืืืื ืจ ืขื ืฉืืืืฉ ื ืืื ืืืื AI ืืคืืชืื - ื ืจืื ืฉื ืืช lovable, base44, ืงืืคืืืืื, ืื ืงืื, ืจืื ืืขืื ืืืื ืืืจืื ืืืกืคืจ ืื ืืืื ืขืืื ืขืืืจื. ืืืืื ืื ืืืฆืืจืฃ ืืืื ืง:
https://calendly.com/aumint/10xdevwith_ai?month=2025-03&date=2025-03-27
1 417
ืืื ืคืชืืชื ืืช ืืงืื
ืืืงืฉืชื ื Lovable ืืืชืื ืืคืืืงืฆืื ืฉืชืืงื ืงืืฉืืจ ื URL ืืชืืืฆืจ ืื ืืืื ืืืฆืจ ืืืืื ืขื ืืืืืื ืฉื, ืืื ืืฉืืื ืืชืจืื ืืช ืืกืคืจืืืช. ืืฉืืื ืฉืื ืืืื ืงื ืืื ืืืงืฉืชื ืืื ื ืื ืฉืืืงืฉ ืืช ืืจืื ืื ืืืืืช ืฉืื ืืกืคืจืืืช ืืืื ื ืืืื ืขื ืืืืื ืื URL ืฉืืชืืืืืช ืืจืื ืฉืื. ืื ืืงื ืื ืงืฆืช ืืื ืืื ืืกืืฃ ืืื ืืืฆืื ืืช ืืืคืืืงืฆืื ืืื:
https://colorlingo-quizzy.lovable.app/
ืืืจื ืืื ืืฉืืงืื ืืจืืฉืชื ืฉืืื ืงืฆืช ืืจืื ืื ืืืืชื ืืงืื ืืื ืืืฆืื ืืช ืืคืื ืงืฆืื ืืืื ืฉืืืฆืืื ืืช ืืืืืื ืืืืื ืง:
// This would be populated with real data from the URL and filtered by level
// For now, we're creating dummy words for the custom quiz
const generateDummyWords = (url: string, level: SpanishLevel) => {
// Extract domain name for demonstration
let domain = '';
try {
domain = new URL(url).hostname.replace('www.', '');
} catch {
domain = 'example';
}
// These would actually come from scraping and NLP processing
const allWordPairs = [
// A1 level words (beginner)
{ english: "hello", spanish: "hola", level: "A1" },
{ english: "goodbye", spanish: "adiรณs", level: "A1" },
{ english: "thank you", spanish: "gracias", level: "A1" },
{ english: "please", spanish: "por favor", level: "A1" },
// A2 level words (elementary)
{ english: "welcome", spanish: "bienvenido", level: "A2" },
{ english: "friend", spanish: "amigo", level: "A2" },
{ english: "family", spanish: "familia", level: "A2" },
{ english: "today", spanish: "hoy", level: "A2" },
// B1 level words (intermediate)
{ english: "website", spanish: "sitio web", level: "B1" },
{ english: domain, spanish: domain, level: "B1" },
{ english: "language", spanish: "idioma", level: "B1" },
{ english: "content", spanish: "contenido", level: "B1" },
// B2 level words (upper intermediate)
{ english: "experience", spanish: "experiencia", level: "B2" },
{ english: "develop", spanish: "desarrollar", level: "B2" },
{ english: "improve", spanish: "mejorar", level: "B2" },
{ english: "progress", spanish: "progreso", level: "B2" },
// C1 level words (advanced)
{ english: "fluency", spanish: "fluidez", level: "C1" },
{ english: "proficient", spanish: "competente", level: "C1" },
{ english: "articulate", spanish: "articular", level: "C1" },
{ english: "communicate", spanish: "comunicar", level: "C1" },
// C2 level words (proficiency)
{ english: "mastery", spanish: "dominio", level: "C2" },
{ english: "nuance", spanish: "matiz", level: "C2" },
{ english: "sophisticated", spanish: "sofisticado", level: "C2" },
{ english: "eloquent", spanish: "elocuente", level: "C2" },
];
// Filter words based on selected level or lower
const levelOrder = ["A1", "A2", "B1", "B2", "C1", "C2"];
const levelIndex = levelOrder.indexOf(level);
const filteredWords = allWordPairs.filter(word =>
levelOrder.indexOf(word.level as SpanishLevel) <= levelIndex
);
// Shuffle the array to make it more random and take 10 words
return filteredWords
.sort(() => 0.5 - Math.random())
.slice(0, 10)
.map(({ english, spanish }) => ({ english, spanish }));
};
ืืงืืฆืืจ ืืื ืืืืจื ืขืื ืขืืื. ืืฃ ืืืื ืืืืื ืง ืื ืืืืขื ืืืืื ืืืฆืจ ืืืืื.
(ืืืืจืกื ืืฉื ืืื ืฉืื ืื ืื ืืืชื ื ืืื ื ืืื ืืกืืื ืืืจืช).
ืขืืฉืื ืืืื ืืื ืืืกืืช ื ืืื ืื ืงื ืืืืืช ืืืชื, ืืื ืื ื ืืืฉื ืฉืืื ืืืืืฉ ืืช ืืืฆืืจืชืืืช ืฉื ื AI, ืฉืืื ืืื ืืืืืืฉื ืฉืื: ืืฉืืื ืื ืืืืข ืืื ืื ืขืืฆืจ ืืฉืืื ืื ืืืฉืื, ืคืฉืื ืืฉืืื ืงืื ืืืืืืจ ืืืื ืกืืคื ืฉื ืงืืืื ืฉืืื ืืืื ืขืืืื. ืืืื ืืขืื ื POC-ืื ืงืื ืื ืืฉืื ืื ื ืืชืื ืืฆืืืช ืื ืืืงืจืื ืจืขืืื, ืืจืื ืคืืืช ืจืืืื ืื ืืืขืจืืช ืฉืฆืจืืื ืืคืืืฉ ืืฉืชืืฉืื ืืืืชืืื.
Available now! Telegram Research 2025 โ the year's key insights 
