Use Tailwind CSS with RN for awesome styling!
Use the Google Distance Matrix API to calculate Travel time and Distance (+ Cost!)
Use the Directions Google API for real navigation!
Use Google places API for real navigations!
Use apple & google maps for iOS & Android
Use React Native Navigation to navigate between screens!
Use React Native Elements to elevate your app design!
GitHub Issues
The GitHub Issues integration allows you to search and reference your issues from the commit message box in VS, in response to this suggestion ticket. You can reference an issue or a pull request by typing # or clicking on the # button in the lower right side of the commit message text box. If you weren't already authenticated to access related issues, you will now be prompted to sign in to take advantage of this feature.
Line Unstaging
To continue improving our line-staging (aka interactive staging) feature, we've added unstage. You can now use the tool tip option to unstage changes, line by line, as requested here Unstage individual lines and hunks in a file - 4 votes
Arm64
We continue to build native support for Arm64 on Windows 11 for the most popular developer scenarios. We now support the .NET Multi-platform App UI (MAUI) workload on Arm64 Visual Studio.
C++
- Available as a preview feature, you can now view Unreal Engine logs without leaving VS. To see the logs from the Unreal Engine Editor, click View > Other Windows > UE Log. To filter your logs, click on the "Categories" or "Verbosity" dropdowns. Since this is an experimental feature, feedback is greatly appreciated.
- You can now import STM32CubeIDE projects for embedded development within Visual Studio with File > Open > Import STM32CubeIDE project. This generates a CMake project with device flashing and debugging settings for STLink. You must have the STM32CubeIDE installed with the board support package for your device. More details available here.
- You can use the new CMake Debugger to debug your CMake scripts at build time. You can set breakpoints based on filenames, line numbers, and when CMake errors are triggered. Additionally, you can view call stacks of filenames and watch defined variables. Currently, this only works with bundled CMake, and projects targeting WSL or remote machines are not supported yet. We are actively working to add more support to the CMake debugger, and feedback is greatly appreciated.
ایجاد فرم لاگین
فرم لاگینی را که به برنامهی نمایش لیست فیلمهای تکمیل شدهی تا قسمت 17، اضافه خواهیم کرد، یک فرم بوت استرپی است و میتوانید جزئیات بیشتر مزین سازی المانهای این نوع فرمها را با کلاسهای بوت استرپ، در مطلب «کار با شیوهنامههای فرمها در بوت استرپ 4» مطالعه کنید.
در ابتدا فایل جدید src\components\loginForm.jsx را ایجاد کرده و سپس توسط میانبرهای imrc و cc در VSCode، ساختار ابتدایی کامپوننت جدید LoginForm را ایجاد میکنیم:
import React, { Component } from "react"; class LoginForm extends Component { render() { return <h1>Login</h1>; } } export default LoginForm;
import LoginForm from "./components/loginForm"; //... function App() { return ( <React.Fragment> <NavBar /> <main className="container"> <Switch> <Route path="/login" component={LoginForm} /> <Route path="/movies/:id" component={MovieForm} /> // ... </Switch> </main> </React.Fragment> ); }
<NavLink className="nav-item nav-link" to="/login"> Login </NavLink>
اکنون نوبت به افزودن فرم بوت استرپی لاگین به فایل loginForm.jsx رسیدهاست:
import React, { Component } from "react"; class LoginForm extends Component { render() { return ( <form> <div className="form-group"> <label htmlFor="username">Username</label> <input id="username" type="text" className="form-control" /> </div> <div className="form-group"> <label htmlFor="password">Password</label> <input id="password" type="password" className="form-control" /> </div> <button className="btn btn-primary">Login</button> </form> ); } } export default LoginForm;
- ابتدا المان form به صفحه اضافه میشود.
- سپس هر ورودی، داخل یک div با کلاس form-group، محصور میشود. کار آن تبدیل یک برچسب و فیلد ورودی، به یک گروه از ورودیهای بوت استرپ است.
- در اینجا هر برچسب دارای یک ویژگی for است. اما چون قرار است عبارات jsx، به معادلهای جاوا اسکریپتی ترجمه شوند، نمیتوان از واژهی کلیدی for در اینجا استفاده کرد. به همین جهت از معادل react ای آن که htmlFor است، در کدهای فوق استفاده کردهایم؛ شبیه به نکتهای که در مورد تبدیل ویژگی class به className وجود دارد. مقدار هر ویژگی htmlFor نیز به id فیلد ورودی متناظر با آن تنظیم میشود. به این ترتیب اگر کاربر بر روی این برچسب کلیک کرده و آنرا انتخاب کند، فیلد متناظر با آن، دارای focus میشود.
- فیلدهای ورودی نیز دارای کلاس form-control هستند.
با این خروجی نهایی در مرورگر:
مدیریت ارسال فرمها
به صورت پیش فرض و استاندارد، دکمهی افزوده شدهی به المان form، سبب ارسال اطلاعات آن به سرور و سپس بارگذاری کامل صفحه میشود. این رفتاری نیست که در یک برنامهی SPA مدنظر باشد. برای مدیریت این حالت، میتوان از رخداد onSubmit هر المان فرم، استفاده کرد:
class LoginForm extends Component { handleSubmit = e => { console.log("handleSubmit", e); e.preventDefault(); // call the server }; render() { return ( <form onSubmit={this.handleSubmit}> //...
دسترسی مستقیم به المانهای فرمها
پس از فراخوانی متد preventDefault، کار مدیریت ارسال فرم به سرور را باید خودمان مدیریت کنیم و دیگر رخداد full post back استاندارد به سمت سرور را نخواهیم داشت. در جاوا اسکریپت خالص برای دریافت مقادیر وارد شدهی توسط کاربر میتوان نوشت:
const username = document.getElementById("username").value;
برای دسترسی به یک المان DOM در React، باید یک reference را به آن نسبت داد. برای این منظور یک خاصیت جدید را در سطح کلاس کامپوننت، ایجاد کرده و آنرا با React.RefObject، مقدار دهی اولیه میکنیم:
class LoginForm extends Component { username = React.createRef();
<input ref={this.username} id="username" type="text" className="form-control" />
handleSubmit = e => { e.preventDefault(); // call the server const username = this.username.current.value; console.log("handleSubmit", username); };
class LoginForm extends Component { username = React.createRef(); componentDidMount = () => { this.username.current.focus(); };
البته روش بهتری نیز برای انجام اینکار وجود دارد. المانهای JSX دارای ویژگی autoFocus نیز هستند که دقیقا همین کار را انجام میدهد:
<input autoFocus ref={this.username} id="username" type="text" className="form-control" />
تبدیل المانهای فرمها به Controlled elements
در بسیاری از اوقات، فرمهای ما state خود را از سرور دریافت میکنند. فرض کنید که در حال ایجاد یک فرم ثبت اطلاعات فیلمها هستیم. در این حالت باید بر اساس id فیلم، اطلاعات آن را از سرور دریافت و در state ذخیره کرد؛ سپس فیلدهای فرم را بر اساس آن مقدار دهی اولیه کرد. برای نمونه در فرم لاگین میتوان state را با شیء account، به صورت زیر مقدار دهی اولیه کرد:
class LoginForm extends Component { state = { account: { username: "", password: "" } };
ابتدا ویژگی value فیلد برای مثال username را به خاصیت username شیء account موجود در state متصل میکنیم:
<input value={this.state.account.username}
<input value={this.state.account.username} onChange={this.handleChange}
handleChange = e => { const account = { ...this.state.account }; //cloning an object account.username = e.currentTarget.value; this.setState({ account }); };
مدیریت دریافت اطلاعات چندین فیلد ورودی
تا اینجا موفق شدیم اطلاعات state را به تغییرات فیلد username در فرم لاگین متصل کنیم؛ اما فیلد password را چگونه باید مدیریت کرد؟ برای اینکه تمام این مراحل را مجددا تکرار نکنیم، میتوان از مقدار دهی پویای خواص در جاوا اسکریپت که توسط [] انجام میشود استفاده کرد:
handleChange = e => { const account = { ...this.state.account }; //cloning an object account[e.currentTarget.name] = e.currentTarget.value; this.setState({ account }); };
<input id="password" name="password" value={this.state.account.password} onChange={this.handleChange} type="password" className="form-control" />
یک نکته: میتوان توسط Object Destructuring، تکرار e.currentTarget را حذف کرد:
handleChange = ({ currentTarget: input }) => { const account = { ...this.state.account }; //cloning an object account[input.name] = input.value; this.setState({ account }); };
آشنایی با خطاهای متداول دریافتی در حین کار با فرمها
فرض کنید خاصیت username را از شیء account موجود در state حذف کردهایم. در زمان نمایش ابتدایی فرم، خطایی را دریافت نخواهیم کرد، اما اگر اطلاعاتی را در آن وارد کنیم، بلافاصله در کنسول توسعه دهندگان مرورگر چنین اخطاری ظاهر میشود:
Warning: A component is changing an uncontrolled input of type text to be controlled. Input elements should not switch from uncontrolled to controlled (or vice versa). Decide between using a controlled or uncontrolled input element for the lifetime of the component. More info: https://fb.me/react-controlled-components
دقیقا چنین اخطاری را با ورود null/undefined بجای "" در حین مقدار دهی اولیهی username در شیء account نیز دریافت خواهیم کرد:
Warning: `value` prop on `input` should not be null. Consider using an empty string to clear the component or `undefined` for uncontrolled components.
ایجاد یک کامپوننت ورود اطلاعات با قابلیت استفادهی مجدد
هر چند در پیاده سازی فعلی سعی کردیم با بکارگیری مقداردهی پویای خواص اشیاء، تکرار کدها را کاهش دهیم، اما باز هم به ازای هر فیلد ورودی باید این مسایل تکرار شوند:
- ایجاد یک div با کلاسهای بوت استرپی.
- ایجاد label و همچنین فیلد ورودی.
- در اینجا مقدار htmlFor باید با مقدار id فیلد ورودی یکی باشد.
- مقدار دهی ویژگیهای value و onChange نیز باید تکرار شوند.
بنابراین بهتر است این تعاریف را استخراج و به یک کامپوننت با قابلیت استفادهی مجدد منتقل کرد. به همین جهت فایل جدید src\components\common\input.jsx را در پوشهی common ایجاد کرده و سپس توسط میانبرهای imrc و sfc، این کامپوننت تابعی بدون حالت را تکمیل میکنیم:
import React from "react"; const Input = ({ name, label, value, onChange }) => { return ( <div className="form-group"> <label htmlFor={name}>{label}</label> <input value={value} onChange={onChange} id={name} name={name} type="text" className="form-control" /> </div> ); }; export default Input;
سپس به کامپوننت فرم لاگین بازگشته و ابتدا آنرا import میکنیم:
import Input from "./common/input";
render() { const { account } = this.state; return ( <form onSubmit={this.handleSubmit}> <Input name="username" label="Username" value={account.username} onChange={this.handleChange} /> <Input name="password" label="Password" value={account.password} onChange={this.handleChange} /> <button className="btn btn-primary">Login</button> </form> );
کدهای کامل این قسمت را از اینجا میتوانید دریافت کنید: sample-18.zip
بررسی WASI
نگاهی دقیق به ASP.NET CORE
ASP.NET Core is a completely new web framework for building modern cloud-based web applications. In this presentation learn all about ASP.NET Core and including the latest features and innovations in MVC. You’ll see how you can build applications that run cross-platform on Windows, Mac and Linux via .NET Core. You’ll also see how ASP.NET Core MVC gives you a unified web programming model for building both web UI and web APIs.