تغییر نام برنامه
برای ios:
وارد پوشه ios در پروژه بشوید و فایل Info.plist
را پیدا کنید. کلید <key>CFBundleDisplayName</key>
را پیدا کنید و مقدار string آن را به نام اپ دلخواهی تان تغییر دهید.
برای اندروید:
وارد فولدر android در پروژه تان بشوید و فایل android/app/src/main/res/values/strings.xml
را پیدا کنید. مقدار تگ <string name="app_name">
را با نام دلخواهی تان تغییر دهید.
تغییر لوگو برنامه
برای ios:
فایل آیکون موجود در مسیر ios/{YourAppName}/Images.xcassets/AppIcon.appiconset
را با فایل دلخواهی خودتان جایگزین کنید.
برای اندروید:
فایل های آیکون موجود در مسیر android/app/src/main/res/mipmap-*
را با فایل های دلخواهی خودتان جایگزین کنید.
- نفیسه افقی 1 سال قبل پاسخ داد
تغییر نام برنامه
برای ios:
وارد پوشه ios در پروژه بشوید و فایل Info.plist
را پیدا کنید. کلید <key>CFBundleDisplayName</key>
را پیدا کنید و مقدار string آن را به نام اپ دلخواهی تان تغییر دهید.
برای اندروید:
وارد فولدر android در پروژه تان بشوید و فایل android/app/src/main/res/values/strings.xml
را پیدا کنید. مقدار تگ <string name="app_name">
را با نام دلخواهی تان تغییر دهید.
تغییر لوگو برنامه
برای ios:
فایل آیکون موجود در مسیر ios/{YourAppName}/Images.xcassets/AppIcon.appiconset
را با فایل دلخواهی خودتان جایگزین کنید.
برای اندروید:
فایل های آیکون موجود در مسیر android/app/src/main/res/mipmap-*
را با فایل های دلخواهی خودتان جایگزین کنید.
- نفیسه افقی 1 سال قبل پاسخ داد
برای پیاده سازی یک لیست dropdown می توانید از کتابخانه react-native-element-dropdown استفاده کنید. با دستور زیر نصبش کنید:
npm install react-native-element-dropdown --save
برای استفاده هم می توانید از مثال زیر الگو بگیرید:
import React, { useState } from 'react';
import { StyleSheet } from 'react-native';
import { Dropdown } from 'react-native-element-dropdown';
import AntDesign from '@expo/vector-icons/AntDesign';
const data = [
{ label: 'Item 1', value: '1' },
{ label: 'Item 2', value: '2' },
{ label: 'Item 3', value: '3' },
{ label: 'Item 4', value: '4' },
{ label: 'Item 5', value: '5' },
{ label: 'Item 6', value: '6' },
{ label: 'Item 7', value: '7' },
{ label: 'Item 8', value: '8' },
];
const DropdownComponent = () => {
const [value, setValue] = useState(null);
return (
<Dropdown
style={styles.dropdown}
placeholderStyle={styles.placeholderStyle}
selectedTextStyle={styles.selectedTextStyle}
inputSearchStyle={styles.inputSearchStyle}
iconStyle={styles.iconStyle}
data={data}
search
maxHeight={300}
labelField="label"
valueField="value"
placeholder="Select item"
searchPlaceholder="Search..."
value={value}
onChange={item => {
setValue(item.value);
}}
renderLeftIcon={() => (
<AntDesign style={styles.icon} color="black" name="Safety" size={20} />
)}
/>
);
};
export default DropdownComponent;
const styles = StyleSheet.create({
dropdown: {
margin: 16,
height: 50,
borderBottomColor: 'gray',
borderBottomWidth: 0.5,
},
icon: {
marginRight: 5,
},
placeholderStyle: {
fontSize: 16,
},
selectedTextStyle: {
fontSize: 16,
},
iconStyle: {
width: 20,
height: 20,
},
inputSearchStyle: {
height: 40,
fontSize: 16,
},
});
*از placeholderStyle
و selectedTextStyle
و inputSearchStyle
برای استایل دهی استفاده کنید. (لیست کامل prop ها را اینجا ببینید)
*اگر از dropdown داخل Formik
استفاده می کنید، می توانید با توابع زیر مقدار آن را دریافت کنید:
onChangeText={handleChange}
onChange={item => {
values["gender"] = item.value;
}}
- نفیسه افقی 1 سال قبل پاسخ داد
خود react native کتابخانه ای بنام ActivityIndicator دارد که می توانید از آن استفاده کنید. بصورت زیر اسفاده کنید:
import React from 'react';
import {ActivityIndicator, StyleSheet, View} from 'react-native';
const App = () => (
<View style={[styles.container, styles.horizontal]}>
<ActivityIndicator />
<ActivityIndicator size="large" />
<ActivityIndicator size="small" color="#0000ff" />
<ActivityIndicator size="large" color="#00ff00" />
</View>
);
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
},
horizontal: {
flexDirection: 'row',
justifyContent: 'space-around',
padding: 10,
},
});
export default App;
- نفیسه افقی 1 سال قبل پاسخ داد
- آخرین فعالیت در 1 سال قبل
یکی از محبوب ترین کتابخانه ها برای استفاده از آیکون در react native ، کتابخانه react native vector icons
است. اول بصورت زیر نصبش کنید:
npm install react-native-vector-icons --save
بعد کافی است تا دسته آیکون هایی که می خواهید استفاده کنید را از یک فونت خاص ایمپورت کنید (مثلا: FontAwesome
) . حالا بصورت زیر می توانید از آن ها استفاده کنید:
// Example to Use React Native Vector Icons
// https://aboutreact.com/react-native-vector-icons/
// Import React
import React from 'react';
// Import required component
import {SafeAreaView, StyleSheet, Text, View} from 'react-native';
// Import vector icons
import Icon from 'react-native-vector-icons/FontAwesome';
const App = () => {
return (
<SafeAreaView style={{flex: 1}}>
<View style={{flex: 1, padding: 16}}>
<View style={styles.container}>
<Text style={styles.heading}>
Example to Use React Native Vector Icons
</Text>
<View style={styles.iconContainer}>
<Text>
<Icon name="rocket" size={30} color="#900" />
</Text>
{/* Icon Component */}
<Icon name="rocket" size={30} color="#900" />
</View>
<View style={{marginTop: 16, marginBottom: 16}}>
{/* Icon.Button Component */}
<Icon.Button
name="facebook"
backgroundColor="#3b5998"
onPress={() => alert('Login with Facebook')}>
Login with Facebook
</Icon.Button>
</View>
</View>
<Text style={styles.footerTitle}>Vector Icons</Text>
<Text style={styles.footerText}>www.aboutreact.com</Text>
</View>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
heading: {
fontSize: 20,
textAlign: 'center',
marginBottom: 20,
},
iconContainer: {
marginTop: 16,
marginBottom: 16,
justifyContent: 'center',
alignItems: 'center',
textAlign: 'center',
},
footerTitle: {
fontSize: 18,
textAlign: 'center',
color: 'grey',
},
footerText: {
fontSize: 16,
textAlign: 'center',
color: 'grey',
},
});
export default App;
*به دو صورت زیر می توانید از icon ها استفاده کنید:
<Icon.Button
name="facebook"
backgroundColor="#3b5998"
onPress={() => alert('Login with Facebook')}>
Login with Facebook
</Icon.Button>
<Icon name="rocket" size={30} color="#900" />
*اگر روی گوشی های اندروید آیکونی نمایش داده نشد، این کار را بکنید: داخل فایل build.gradle در پوشه android/build ، خط زیر را به انتهای فایل اضافه کنید و مجدد بیلد بگیرید (npm run android):
apply from: file("../../node_modules/react-native-vector-icons/fonts.gradle")
*react native vector icons چندین بسته معروف از آیکن ها را ساپورت می کند. لینک آیکن ها و اسامی شان را ببینید:
Ionicons
Octicons
Foundation Icons
Entypo
Zocial
Evil Icons
*اگر از این پکیج ها استفاده می کنید باید هر کدام را جدا ایمپورت و استفاده کنید:
import SimpleLineIcons from 'react-native-vector-icons/SimpleLineIcons';
// Use an icon in your component
<SimpleLineIcons name="user" size={30} color="black" />;
- نفیسه افقی 1 سال قبل پاسخ داد
- آخرین فعالیت در 1 سال قبل
سلام دوست عزیز،
بله دقیقاً راه حل همینی هست که گفتید. یعنی باید کیف پول برای هر کاربر تعریف کنید، کاربر شارژش کنه و اگر جایی برای رزرو خالی شد، سیستم اتومات مبلغ رو از کیف پولش برداشت کنه. البته این در صورتی هست که بخواهید پرداخت هنگام خرید بلیط انجام بشه. اگر بخواهید که کاربر برای رزرو پولی پرداخت نکنه و بر اساس اعتبارش رزرو کنه که لازم به اینکار نیست.
- نفیسه افقی 1 سال قبل پاسخ داد
برای اینکار می توانید از redux
یا context
استفاده کنید. redux کمی پیچیده تر است، اما می توانید از هوک useContext
برای پروژه های کوچکتر استفاده کنید. برای این کار، اول یک فایل (مثلا بنام UserContext.js
) بسازید و کد زیر را در آن قرار دهید:
import React, { createContext, useState, useEffect } from 'react';
import AsyncStorage from '@react-native-async-storage/async-storage';
const UserContext = createContext();
const UserProvider = ({ children }) => {
const [userData, setUserData] = useState({
id: null,
token: null,
});
useEffect(() => {
async function fetchData() {
const token = await AsyncStorage.getItem('token');
const id = await AsyncStorage.getItem('user_id');
const storedUserData = {
id: id, // Example user ID
token: token, // Example user token
};
setUserData(storedUserData);
}
fetchData();
}, []);
return (
<UserContext.Provider value={userData}>
{children}
</UserContext.Provider>
);
};
export { UserProvider, UserContext };
در این مثال، ما دو متغیری که از کاربر روی حافظه AsyncStorage ذخیره کرده بودیم را می خوانیم (id و token). شما می توانید هر متغیر با هر مقداری که می خواهید تعریف کنید.
function App(): JSX.Element {
const Tab = createBottomTabNavigator();
return (
<UserProvider>
<NavigationContainer>
<LoginNavigation></LoginNavigation>
</NavigationContainer>
</UserProvider>
);
}
export default App;
حالا باید این UserProvider
را قبل از اولین تگ برنامه مان ، یعنی اولین فایلی که برنامه از آنجا لود می شود ، قرار دهیم (می توانید فایل index.js یا App.js باشد)
بعد بصورت زیر می توانیم در همه جای پروژه (در هر کامپوننتی) از متغیرهایمان استفاده کنیم:
import { UserContext } from '../../UserContext';
onst { id, token } = useContext(UserContext);
- نفیسه افقی 1 سال قبل پاسخ داد
- آخرین فعالیت در 1 سال قبل
می توانید از AsyncStorage
برای این کار استفاده کنید. با دستور زیر آن را نصب کنید:
npm install @react-native-async-storage/async-storage
برای نوشتن روی AsyncStorage
از کد زیر استفاده کنید:
import AsyncStorage from '@react-native-async-storage/async-storage';
//cache user token:
await AsyncStorage.setItem('token', token);
و برای خواندن از حافظه از کد زیر استفاده کنید:
const token = await AsyncStorage.getItem('token');
- نفیسه افقی 1 سال قبل پاسخ داد
یکی از راههایی که می توانید به api درخواست http ارسال کنید، استفاده از axios است. axios کتابخانه react است و چون react native بر پایه react نوشته شده ، می توانید از axios هم در اینجا استفاده کنید. از مثال زیر استفاده کنید:
import axios from 'axios';
axios({
method: 'get',
url: link,
headers: {"Content-Type": "application/json"}
}).then((response) => {
//do something with result
})
.catch((error) => {
console.error('Error fetching data:', error);
});
- نفیسه افقی 1 سال قبل پاسخ داد
- آخرین فعالیت در 1 سال قبل
environment variable متغیری است که بصورت global تعریف می شود و قابل دسترسی برای همه هم نیست. بنابرین اگر کدی دارید که می خواهید درون برنامه تان بطور مرنب استفاده کنید و یا قابل دیدن برای سایرین نباشد، می توانید داخل یک environment variable قرارش دهید.
برای تعریف environment variable در react native ، ابتدا کتابخانه زیر را نصب کنید:
npm install @env
حالا داخل root پروژه یک فایل بنام env. بسازید و متغیرهایتان را با فرمت زیر تعریف کنید:
API_URL=https://api.example.com
DEBUG=true
بعد باید فایل babel.config.js
را بصورت زیر آپدیت کنید تا آدرس فایل env. را داشته باشد:
module.exports = {
presets: ['module:metro-react-native-babel-preset'],
plugins: [
[
'module:react-native-dotenv',
{
moduleName: '@env',
path: '.env',
blacklist: null,
whitelist: null,
safe: false,
allowUndefined: true,
},
],
],
};
بصورت زیر هم می توانید داخل برنامه تان از environmrnt variable ها استفاده کنید:
process.env.DEBUG
*برای تعریف environment variable در react و nest.js ، لینک ها را ببینید.
- نفیسه افقی 1 سال قبل پاسخ داد
- آخرین فعالیت در 1 سال قبل
برای این کار می توانید از کتابخانه react-native-floating-action
استفاده کنید. با کد زیر نصبش کنید:
npm install react-native-floating-action
با دستور زیر، ایمپورتش کنید:
import { FloatingAction } from 'react-native-floating-action';
و بصورت زیر استفاده کنید:
const YourComponent = () => {
const actions = [
{
text: 'Option 1',
icon: require('path-to-your-icon-1.png'),
name: 'option1',
position: 2,
},
{
text: 'Option 2',
icon: require('path-to-your-icon-2.png'),
name: 'option2',
position: 1,
},
// Add more options as needed
];
return (
<View style={{ flex: 1 }}>
{/* Your main content goes here */}
{/* Floating Action Button */}
<FloatingAction
actions={actions}
onPressItem={(name) => {
// Handle button press based on the selected option
console.log(`Option selected: ${name}`);
// You can navigate to different screens based on the selected option
}}
/>
</View>
);
};
export default YourComponent;
* هر action را هم می توانید جداگانه customize کنید. این لینک را ببینید.
- نفیسه افقی 1 سال قبل پاسخ داد
اگر می خواهید فونت خودتان را در react native استفاده کنید، این مراحل را انجام دهید:
1- گذاشتن فایل فونت ها در پروژه
در قسمت root
پروژه، یک فولدر بنام assets
بسازید و داخل این فولدر ، یک فولدر دیگر بنام fonts بسازید و فایل فونت ها (.ttf) را در آنجا قرار دهید.
2- ساخت فایل react-native.config.js
در همان root پروژه، یک فایل بنام react-native.config.
js
بسازید و کد زیر را داخل آن قرار دهید:
module.exports = {
project: {
ios: {},
android: {},
},
assets: ['./assets/fonts'],
};
3- لینک فولدر asset به پروژه
حالا دستور زیر را در ترمینال وارد کنید:
npx react-native-asset
حالا می توانید از فونت های سفارشی خودتان در همه جای پروژه استفاده کنید. (دقت کنید که باید دقیقا نام فایل فونت را استفاده کنید). یک نمونه از استفاده از فونت:
import {StyleSheet, Text, View} from 'react-native';
import React from 'react';
const App = () => {
return (
<View style={styles.container}>
<Text style={styles.quicksandRegular}>
This text uses a quick sand font
</Text>
<Text style={styles.quicksandLight}>
This text uses a quick sand light font
</Text>
<Text style={styles.ralewayThin}>
This text uses a thin italic raleway font
</Text>
<Text style={styles.ralewayItalic}>
This text uses a thin italic raleway font
</Text>
</View>
);
};
export default App;
const styles = StyleSheet.create({
container: {
backgroundColor: 'lavender',
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
quicksandLight: {
fontFamily: 'Quicksand-Light',
fontSize: 20,
},
quicksandRegular: {
fontFamily: 'Quicksand-Regular',
fontSize: 20,
},
ralewayItalic: {
fontFamily: 'Raleway-Italic',
fontSize: 20,
},
ralewayThin: {
fontFamily: 'Raleway-ThinItalic',
fontSize: 20,
},
});
- نفیسه افقی 1 سال قبل پاسخ داد
برای اینکار می توانید داخل تابع functions.php از کد زیر استفاده کنید:
function custom_woocommerce_text($translated_text, $text, $domain) {
switch ($translated_text) {
case 'Product':
$translated_text = 'File';
break;
// Add more cases for other phrases you want to customize
// Example for changing "Add to Cart" button text:
// case 'Add to cart':
// $translated_text = 'Custom Button Text';
// break;
}
return $translated_text;
}
add_filter('gettext', 'custom_woocommerce_text', 20, 3);
به جای Product
و File
هر عبارتی که می خواهید را قرار دهید.
- نفیسه افقی 1 سال قبل پاسخ داد
سلام دوست عزیز، بستگی به میزان فیچرهایی داره که میخواهید داشته باشه، برای چنین پروژه هایی باید برنامه نویسی کرد. اگر تمایل داشتید میتونم در واتساپ بیشتر راهنمایی تون کنم: 09352333881
- نفیسه افقی 1 سال قبل پاسخ داد
فرض کنید یک اپلیکیشن چت نوشتیم و می خواهیم بصورت real time پیام ها را نمایش دهیم. یعنی وقتی کاربر1 به کاربر2 پیام می فرستد، نیازی به رفرش کردن صفحه نباشد. یا مثلاً وقتی کاربر1 وارد صفحه چت شد، آنلاین بودنش به تمامی دوستانش نمایش داده شود. برای این طور کارها از مفهومی بنام websocket استفاده می کنیم.
websocket نوعی از کانکشن است. برعکس کانکشن http که بعد از ارسال داده بسته می شود، websocket کانکشنی است که تا زمانیکه دو طرف بخواهند باز می ماند و می توان بینشان داده رد و بدل کرد. کانکشن websocket به جای http با ws شروع می شود.
حالا چطور از websocket استفاده کنیم؟
websocket را باید برای server و client جدا پیاده سازی کنیم.
اول لازم است تا روی سرور یک gateway باز کنیم. gateway سروری است که روی یک پورت بالا می آید و همیشه بالا است. client ها با websocket به آن connect و disconnect می شوند، message ارسال می کنند و به تمامی message هایی که ارسال می شود گوش می دهند. (gateway هم می تواند به تمامی client هایی که وصل هستند، یک message را ارسال کند)
مثلاً وقتی کاربر1 وارد چت می شود، با یک websocket به gateway وصل می شود. حالا ما می توانیم به تمامی کاربرانی که داخل آن چت روم هستند آنلاین شدن کاربر1 را اطلاع دهیم. یا اگر کاربر1 پیامی به کاربر2 ارسال کند، پیام را بلافاصله به کاربر2 ارسال کنیم. (چون کاربر2 هم به gateway متصل است)
برای مثال، ما اینجا در سمت client از react استفاده می کنیم و در سمت سرور از nest.js
سمت سرور
یک پروژه nest.js بسازید. بهتر است پروژه websocket را از پروژه اصلی back-end تان جدا کنید. (تا به تداخل depency ها برنخورید. می توانید هر کدام را هم روی یک پورت جدا بالا بیاورید)
کتابخانه های زیر را نصب کنید:
npm install socket.io @nestjs/websockets
داخل فولدر src
پروژه یک فولدر بنام websocket
بسازید و دو فایل با نامهای websocket.module.ts
و websocket.service.ts
بسازید.
فایل یک ماژول است که باید فایل را به عنوان provider برایش تعریف کنید:
// websocket.module.ts
import { Module } from '@nestjs/common';
import { WebSocketService } from './websocket.service'; // Import your WebSocket gateway
@Module({
providers: [WebSocketService], // Add your WebSocket gateway here
})
export class WebSocketModule {}
باید داخل فایل app.module.ts
هم ماژولی که ساختید را ایمپورت کنید:
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { WebSocketModule } from './websocket/websocket.module';
@Module({
imports: [WebSocketModule],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
فایل websocket.service.ts
، فایل اصلی است که وطیفه اش ساختن gateway است:
import { ConnectedSocket, MessageBody, OnGatewayConnection, OnGatewayDisconnect, SubscribeMessage, WebSocketGateway, WebSocketServer } from '@nestjs/websockets';
import { Server } from 'socket.io';
import { Socket } from 'socket.io';
import { Logger } from '@nestjs/common';
@WebSocketGateway()
export class WebSocketService implements OnGatewayConnection, OnGatewayDisconnect {
@WebSocketServer()
server: Server;
private readonly logger = new Logger(WebSocketService.name);
constructor() {
console.log('WebSocketService initialized');
}
afterInit(server: Server) {
console.log('Initialized');
}
handleConnection(client: Socket) {
console.log(`Client connected: ${client.id}`);
// Handle connection event
}
handleDisconnect(client: Socket) {
console.log(`Client disconnected: ${client.id}`);
// Handle disconnection event
}
@SubscribeMessage('chat_message')
handleMessage(@MessageBody() data: string, @ConnectedSocket() client: Socket) {
console.log(`Received message from ${client.id}: ${data}`);
// Handle received message
this.server.emit('chat_message', data); // Broadcast the message to all connected clients
}
@SubscribeMessage('joinChatRoom')
handlejoinChatRoom(@MessageBody() data: string, @ConnectedSocket() client: Socket) {
console.log(`joinChatRoom with id : ${data}`);
this.server.emit('joinChatRoom', data);
}
@SubscribeMessage('leftChatRoom')
handleLeftChatRoom(@MessageBody() data: string, @ConnectedSocket() client: Socket) {
this.server.emit('leftChatRoom', data);
}
@SubscribeMessage('events')
handleEvent(@MessageBody() data: string): string {
return data;
}
}
*SubscribeMessage('joinChatRoom')
مشخص می کند پیامی که ارسال و دریافت می شود با چه آیدی است (joinChatRoom
) . در سمت فرانت هم باید با همین آیدی پیامتان را ارسال و دریافت کنید.
* this.server.emit('leftChatRoom', data);
پیام را به تمامی client هایی که به این gateway هستند ارسال می کند.
سمت client
سمت فرانت ، مثلا جایی که کاربر صفحه چت را باز می کند، یک useEffect
بنویسید که اتصال websocket را برقرار کند و به event ها (یا همان پیامها) که می آید گوش دهد. با تابع emit
هم می توانید به gateway داده ارسال کنید:
*یادتان باشد که وقتی صفحه چت بسته شد، حتما socket را ببندید.
useEffect( () => {
const initializeSocket = async () =>
{
const socket = io('ws://localhost:5000', { transports: ['websocket'] });
socket.on('chat_message', async (chat_message) => {
console.log("chat_message",chat_message);
});
socket.on('joinChatRoom', async (joinChatRoom) => {
console.log("socket joinChatRoom",joinChatRoom);
});
socket.on('leftChatRoom', async (leftChatRoom) => {
console.log("socket leftChatRoom",leftChatRoom);
});
socket.on('connect', () => {
console.log('Connected to WebSocket');
});
socket.on('disconnect', () => {
console.log('Disconnected from WebSocket');
});
}
return () => {
socket?.emit("leftChatRoom",{user_id:onlineUser._id})
socket?.disconnect(); // Disconnect when the component unmounts
};
}, [messageDialog]);
* ws://localhost:5000
آدرس پورت سرور است که gateway را روی آن بالا آوردید. اگر از https استفاده می کنید به جای ws
از wss
استفاده کنید.
*هر جایی از برنامه ، مثلا وقتی کاربر پیامی جدید ارسال کرد، می توانید به gateway هم ارسال کنید:
socket.emit('chat_message', data );
- نفیسه افقی 2 سال قبل پاسخ داد
- آخرین فعالیت در 2 سال قبل
فرض کنیم یک پایگاه داده با داده های زیاد داریم و کاربر می خواهد روی آن ها سرچ بزند. چند راه مختلف برای این کار وجود دارد:
- یکی از راههای پیاده سازی سرچ این است که کل داده ها را از back-end بگیریم و بعد بنا به کاراکترهایی که کاربر در input وارد می کند، داده موردنظر را نشانش بدهیم. این روش صد در صد بدترین نوع پیاده سازی سرچ است. چون اگر داده ها زیاد باشد، حافظه را پر خواهد کرد. و لزومی هم به داشتن داده های غیرمرتبط با سرچ نیست.
- راه دیگر این است که به ازای هر کاراکتری که کاربر وارد می کند، یک درخواست به back-end بدهیم تا تنها داده هایی که آن کاراکتر را دارند به ما برگرداند. این روش هم بهینه نیست. چون اگر قرار باشد به ازای هر کاراکتری که کاربر وارد می کند یک درخواست به دیتابیس بدهیم ، بار زیادی را روی سرور می اندازیم و قطعا برنامه کند می شود.
- بهینه ترین راهی که بیشتر شبکه های اجتماعی هم از آن استفاده می کنند این است که یک مدت زمان خاصی بعد از تمام شدن تایپ کاربر صبر کنیم و بعد محتوایی که تا به اینجا تایپ کرده را در درخواستمان به back-end بدهیم تا با آن سرچ کند.
حالا چطور روش سوم را در react پیاده سازی کنیم؟
اول یک متغیر برای نگهداری محتوایی که کاربر برای سرچ وارد می کند (searchValue
) می سازیم:
const [searchValue,setSearchValue] = useState("");
حالا تگ input که کاربر داخل آن سرچ می کند را تعریف می کنیم (من از prime react InputText
استفاده کردم):
import { InputText } from "primereact/inputtext";
.
.
.
<InputText
className="search-box"
placeholder="اینجا جستجو کنید ..."
value={searchValue}
onChange={handleSearch}
/>
تابع handleSearch
، محتوای وارد شده را داخل searchValue
قرار می دهد، اما دستور سرچ را نمی دهد:
const handleSearch = (event) => {
const { value } = event.target;
setSearchValue(value);
};
حالا یک useEffect
تعریف می کنیم که با مقداری تاخیر (در اینجا 500 میلی ثانیه) ، دستور سرچ با searchValue
را می دهد.
// Create a debounced version of the API request
useEffect(() => {
const delayedApiRequest = setTimeout(() => {
if (searchValue) {
fetchPosts(searchValue);
}
}, 500);
*در اینصورت موقعی که کاربر در حال تایپ کردن است ما سرچی انجام نمی دهیم و تنها بعد از اینکه 500 میلی ثانیه از تمام شدن تایپش گذشت این کار را انجام می دهیم.
*تابع fetchPosts(searchValue
، کار fetch کردن داده ها را برای سرچ انجام می دهد. اگر از mongo برای دیتابیس استفاده می کنید، می توانید این لینک را برای پیاده سازی سرچ ببینید.
- نفیسه افقی 2 سال قبل پاسخ داد
- آخرین فعالیت در 2 سال قبل
فرض کنید سرویس های مختلفی (GET,POST,DELETE,PATCH,UPDATE) برای back-end نوشتیم، اگر آدرس و پورت back دست هر شخصی بیفتد ، می تواند سرویس های شما را فراخوانی کند (مثلاً پستی یا همه پست ها را حذف کند، آپدیت کند و …)
برای جلوگیری از دسترسی افراد احراز هویت نشده باید چکار کنیم؟
برای این کار باید برای هر سرویس Guard تعریف کنیم. با گذاشتن decorator ای بنام UseGuards@
بالای هر تایع controller می توانیم کاری کنیم که آن تابع تنها پس از احراز هویت اجرا شود. برای احراز هویت هم الگوریتم های مختلفی وجود دارد که ما از یکی از ممعروفترین آن ها یعنی JWT
استفاده می کنیم. نام الگوریتمی که استفاده می کنیم باید کنار decorator نوشته شود. یعنی تابع deleteای که داخل controller نوشتیم ، به این صورت در می آید:
@UseGuards(JwtAuthGuard)
@Delete(":_id")
async deletePage(
@Param("_id") _id: string) {
return await this.pagesService.deletePage(_id);
}
JWT چطور احراز هویت می کند؟
jwt مخفف json web token
است و بدین صورت عمل می کند که وقتی کاربر احراز هویت شد و لاگین کرد، یک توکن با محتوایی که می خواهیم (مثلا شامل id و role کاربر، یا هر داده ای که می خواهیم) می سازیم ، رمزنگاری می کنیم و به front-end می فرستیم. قسمت front-end ، این توکن رمزنگاری شده را در local storage ذخیره می کند و هر زمان خواست http request ای به back-end بفرستد، این توکن را داخل header قرار می دهد و می فرستد. back-end هم این توکن را می گیرد، باز می کند و اگر درست بود، درخواست احراز هویت می شود و تابع مذکور اجرا می شود. در اینصورت تنها کسانی می توانند تابع ما را اجرا کنند که توکن داشته باشند.
*دقت کنید که می توانیم برای توکن تاریخ انقضا تعریف کنیم. (مثلاً اگر کاربر داخل کافی نت لاگین کرده و توکن آنجا ذخیره شده باشد، ممکن است شخص دیگه ای به توکن دسترسی پیدا کن)
برای استفاده از jwt ، لازم است تا کتابخانه های زیر را نصب کنید:
npm install @nestjs/jwt
npm install passport-jwt
npm install jsonwebtoken
چطور بعد از لاگین کاربر، توکن بسازیم و ارسال کنیم؟
در تابعی که برای لاگین کاربر نوشته اید، jsonwebtoken
را ایمپورت کنید:
import * as jwt from 'jsonwebtoken';
و به صورت زیر یک توکن بسازید و امضایش کنید:
async tokenGenerator(payload:AuthPayload)
{
return jwt.sign(payload,process.env.ACCESS_JWT_SECRET);
}
*AuthPayload
مدلی است که برای توکن تعریف کرده ایم. شما هر داده ای از کاربر را می توانید به عنوان توکن تعریف کنید. مثلا ما AuthPayload
را در فولدری بنام auth
و بدین صورت تعریف کرده ایم:
export class AuthPayload
{
user_id:string;
role:string;
}
*payload به معنای توکنی است که رمزش باز شده.
*اکیدا توصیه می شود که کلیدی که توکن به وسیله آن رمزنگاری شده و باز می شود را در فایل env. و به عنوان environment variable ذخیره کنید.
*وقتی کاربر با موفقیت لاگین شد، باید این توکن را به فرانت ارسال کنیم و فرانت هم باید آن ها در local storage ذخیره کند.
چطور JwtAuthGuard
را بسازیم؟
فولدری بنام auth بسازیم و داخل آن باید دو فایل اصلی برای guard و strategy داشته باشید.
فایل jwt-auth-guard.ts
را بدین صورت تعریف کنید:
import { Injectable } from "@nestjs/common";
import { AuthGuard } from "@nestjs/passport";
@Injectable()
export class JwtAuthGuard extends AuthGuard('jwt')
{
}
فایل jwt-strategy.ts
را بدین صورت تعریف کنید:
import {PassportStrategy} from "@nestjs/passport";
import {ExtractJwt, Strategy} from "passport-jwt";
import { Injectable} from "@nestjs/common";
@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
constructor() {
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
ignoreExpiration: false,
secretOrKey: process.env.ACCESS_JWT_SECRET,
})
}
async validate(payload: any) {
return {user_id: payload.user_id, role: payload.role}
}
}
حالا کافی است تا در فایل کنترلری که می خواهیم از guard استفاده کنیم، JwtAuthGuard
را ایمپورت کنیم:
import { JwtAuthGuard } from "src/auth/jwt-auth-guard";
و بالای تابع موردنظرمان، از decorator زیر استفاده کنیم:
@UseGuards(JwtAuthGuard)
*بهتر است auth
را بصورت ماژول در آورید (حتی می توانید تابع تولید کننده توکن tokenGenerator
، را داخل AuthService
قرار دهید):
import { Module } from "@nestjs/common"
import { PassportModule } from "@nestjs/passport"
import { UsersModule } from "src/users/users.module"
import { AuthService } from "./auth.service"
@Module({
imports: [PassportModule.register({ session: true })],
providers: [AuthService],
})
export class AuthModule {}
*دقت کنید که باید داخل فایل app.module
هم jwt را ایمپورت کرده و به عنوان ماژل اضافه کنید:
import { JwtModule } from '@nestjs/jwt';
import { PassportModule } from '@nestjs/passport';
import { JwtStrategy } from './auth/strategy/jwt-strategy';
@Module({
imports: [
PassportModule.register({ defaultStrategy: 'jwt' }),
JwtModule.register({secret: process.env.ACCESS_JWT_SECRET}),
AuthModule],
controllers: [AppController],
providers: [AppService,JwtStrategy],
})
export class AppModule {}
چطور در فرانت ، توکن را داخل http request قرار دهیم و ارسال کنیم؟
به صورت زیر می توانید header درخواستتان را بسازید (توکن را از local storage بگیرید و داخل آن قرار دهید):
const token = JSON.parse(localStorage.getItem('Token'));
const config = { headers: {"Content-Type": "application/json",Authorization: `Bearer ${token}`} }
حالا header را داخل درخواست axios
قرار دهید:
axios.patch("BACK_END_ADRESS", data, config);
- نفیسه افقی 2 سال قبل پاسخ داد
- آخرین فعالیت در 2 سال قبل
با روش symmetric encryption می توانیم این کار را انجام دهیم. بدین صورت که پیامی که می خواهیم ارسال شود را با کمک یک SECRET_KEY
در فرانت رمزنگاری می کنیم، داده رمزنگاری شده را ارسال می کنیم و بعد در بک ، به کمک همان SECRET_KEY
بازش می کنیم.
برای رمزنگاری داده هم می توانیم از الگوریتم AES (Advanced Encryption Standard)
استفاده کنیم. برای این کار، کتابخانه زیر را نصب کنید:
npm install crypto-js
حالا از آن برای رمزنگاری داده تان استفاده کنید:
import React, { useState } from 'react';
import CryptoJS from 'crypto-js';
function App() {
const [message, setMessage] = useState('');
const secretKey = 'your-secret-key';
const encryptData = () => {
const encrypted = CryptoJS.AES.encrypt(message, secretKey).toString();
// Send 'encrypted' to the back end
console.log('Encrypted Data:', encrypted);
};
return (
<div>
<input
type="text"
value={message}
onChange={(e) => setMessage(e.target.value)}
/>
<button onClick={encryptData}>Encrypt and Send</button>
</div>
);
}
export default App;
*تابع encryptData
کار رمزنگاری را انجام می دهد.
در قسمت بک اپلیکیشن بصورت زیر داده رمزنگاری شده را دریافت کنید:
import { Controller, Post, Body } from '@nestjs/common';
import * as CryptoJS from 'crypto-js';
@Controller('data')
export class DataController {
private secretKey = 'your-secret-key';
@Post('decrypt')
decryptData(@Body() encryptedData: string): string {
const bytes = CryptoJS.AES.decrypt(encryptedData, this.secretKey);
const decryptedMessage = bytes.toString(CryptoJS.enc.Utf8);
return decryptedMessage;
}
}
*نکته خیلی مهم: برای امنیت بالاتر و جلوگیری از افشای SECRET_KEY
، بهتر است آن را در فایل env.
و به عنوان environment variable ذخیره کنید.
- نفیسه افقی 2 سال قبل پاسخ داد
- آخرین فعالیت در 2 سال قبل
متغیرهایی وجود دارند که لازم داریم که آن ها را بصورت کلی (global) و در یک فایل تعریف کنیم تا در هر فایلی بتوانیم از آنها استفاده کنیم. به اینطور متغیرها environment variables می گوییم و بطور خاصی باید تعریف و استفاده شوند.
1- nest.js بصورت پیشفرض فایل حاوی متغیرهای environment variables
را لود نمی کند ، برای این کار باید ابتدا پکیج زیر را نصب کنید:
npm install dotenv
2- حالا در فایل main.ts
باید بگویید که متغیرها را لود کند:
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import * as dotenv from 'dotenv'; // Import dotenv
async function bootstrap() {
dotenv.config(); // Load environment variables from .env file
const app = await NestFactory.create(AppModule);
await app.listen(3000);
}
bootstrap();
3- در پروژه nest.js باید فایلی بنام env.
را حتماً در فولدر اصلی پروژه یعنی root بسازید و بصورت زیر متغیرتان را تعریف کنید:
ACCESS_JWT_SECRET=your_secret_here
4- حالا در هر قسمت از برنامه که خواستید ، بصورت زیر می توانید از آن استفاده کنید:
const secret = process.env.ACCESS_JWT_SECRET;
- نفیسه افقی 2 سال قبل پاسخ داد
- آخرین فعالیت در 2 سال قبل
فرض کنید در یک صفحه html قرار داریم و می خواهیم با کلیک بر روی یک باتن، به یک المان خاص scroll کنیم. برای این کار می توانیم از تابع scrollIntoView
استفاده کنیم.
کافی است تا برای المانی که می خواهیم نهایتاً به آن اسکرول کنیم یک رفرنس یا ref
تعریف کنیم و بعد در تابع کلیک باتن مان، تابع scrollIntoView
را روی رفرنس آن المان فراخوانی کنیم:
import { useRef } from 'react';
export default function App() {
const ref = useRef(null);
const handleClick = () => {
ref.current?.scrollIntoView({ behavior: 'smooth' });
};
return (
<div>
<button onClick={handleClick}>Scroll to element</button>
<div style={{ height: '150rem' }} />
<div ref={ref} style={{ backgroundColor: 'lightblue' }}>
Coding Beauty
</div>
<div style={{ height: '150rem' }} />
</div>
);
}
- نفیسه افقی 2 سال قبل پاسخ داد