<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Anubhav on Medium]]></title>
        <description><![CDATA[Stories by Anubhav on Medium]]></description>
        <link>https://medium.com/@jayhawk24?source=rss-f4423e7b8d00------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*RQW6Kzxv-z6ikR-O5yy6cQ.jpeg</url>
            <title>Stories by Anubhav on Medium</title>
            <link>https://medium.com/@jayhawk24?source=rss-f4423e7b8d00------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Mon, 06 Apr 2026 09:06:35 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@jayhawk24/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Dev Accelerator Limited (DevX) IPO — Retail-friendly analysis]]></title>
            <link>https://medium.com/@jayhawk24/dev-accelerator-limited-devx-ipo-retail-friendly-analysis-a7f9e5eb4368?source=rss-f4423e7b8d00------2</link>
            <guid isPermaLink="false">https://medium.com/p/a7f9e5eb4368</guid>
            <dc:creator><![CDATA[Anubhav]]></dc:creator>
            <pubDate>Thu, 11 Sep 2025 18:31:37 GMT</pubDate>
            <atom:updated>2025-09-11T18:42:18.982Z</atom:updated>
            <content:encoded><![CDATA[<h3>Dev Accelerator Limited (DevX) IPO — Retail-friendly analysis</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*bVZ-oer-Af8VxJSn" /><figcaption>Photo by <a href="https://unsplash.com/@reddfrancisco?utm_source=medium&amp;utm_medium=referral">Redd Francisco</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><h3>Quick snapshot</h3><ul><li>Type: 100% Book Built Issue (Fresh Issue only)</li><li>Fresh issue: Up to 2,35,00,000 equity shares (FV ₹2 each); no OFS</li><li>Price band: ₹56 — ₹61 per share</li><li>Issue size (gross): ₹143.35 crore (at upper band)</li><li>Lot size: 235 shares</li><li>Reservations: Up to 1,64,500 shares for Employees; up to 3,29,000 shares for Eligible Shareholders of Dev Information Technology Limited</li><li>Listing: NSE and BSE (NSE designated)</li><li>Key dates: Anchor 9 Sep 2025; Bidding 10–12 Sep 2025; UPI mandate by 5 PM on close day</li></ul><h3>What the company does (in plain words)</h3><ul><li>DevX operates flexible workspaces: coworking desks and managed office spaces; also offers allied services (e.g., payroll management, value-added services).</li><li>Revenue mix is dominated by flexible office spaces; scale-up driven by new centers and higher occupancy under straight-lease and revenue-share models.</li></ul><h3>Use of proceeds (Objects of the Issue)</h3><p>Proposed use of Net Proceeds (deployment to complete by FY26/27; GCP ≤25% of Gross Proceeds):</p><ul><li>₹73.12 crore for fit-outs in 4 Proposed Centers under the straight-lease model (₹731.16 million)</li><li>₹35.00 crore for repayment/prepayment of borrowings and redemption of non-convertible debentures (₹350.00 million)</li><li>Balance for General Corporate Purposes (within SEBI limit)</li><li>Monitoring and interim use per RHP; no external appraisal of objects</li></ul><h3>Financial highlights (Consolidated)</h3><ul><li>Revenue from operations:</li><li>FY23: ₹69.91 crore (₹699.11 million)</li><li>FY24: ₹108.09 crore (₹1,080.87 million)</li><li>FY25: ₹158.88 crore (₹1,588.75 million)</li><li>EBITDA margin (%): FY23 42.74; FY24 59.90; FY25 50.64</li><li>Profit after tax (₹ crore): FY24 ₹0.44; FY25 ₹1.77 (PAT margin low; FY23 had losses per RHP ratio table)</li><li>Operating cash flow (₹ crore): FY23 ₹26.48; FY24 ₹7.56; FY25 ₹93.75</li><li>Note: FY25 OCF is strong despite modest PAT, implying working-capital movements/advances supported cash generation.</li></ul><h3>Capital structure and share count</h3><ul><li>Face value: ₹2 per share</li><li>Pre-issue paid-up equity share capital (FY25): ₹169.15 million (₹16.915 crore)</li><li>Shares outstanding (pre-issue): ≈ 8.4575 crore (84,575,000) at FV ₹2</li><li>Fresh issue shares: 2.35 crore (23,500,000)</li><li>Shares outstanding (post-issue): ≈ 10.8075 crore (108,075,000)</li><li>Promoter &amp; Promoter Group holding: 3,32,01,850 shares (49.80%) pre-issue; inferred ~30.72% post-issue on expanded base</li><li>Customer concentration: top-10 and related-party contributions are meaningful</li></ul><h3>Valuation (at the price band)</h3><p>Market cap (post-issue):</p><ul><li>At ₹56: ≈ ₹605.22 crore</li><li>At ₹61: ≈ ₹659.26 crore</li></ul><p>FY25 Revenue: ₹158.88 crore; EBITDA margin 50.64% → EBITDA ≈ ₹80.45 crore</p><p>P/S (FY25):</p><ul><li>At ₹56: ≈ 3.81x</li><li>At ₹61: ≈ 4.15x</li></ul><p>EPS (FY25):</p><ul><li>PAT ₹1.77 crore on post-issue shares (10.8075 cr) → EPS ≈ ₹0.164</li><li>P/E (post-issue): ~341x at ₹56; ~372x at ₹61</li><li>For reference, on pre-issue shares (8.4575 cr), EPS ≈ ₹0.210 → P/E ~267x–291x</li><li>EV-based metrics: Pending net debt/lease liability details; EV/Revenue and EV/EBITDA likely more meaningful than P/E given depreciation/finance costs.</li></ul><h3>Valuation — EV snapshot</h3><ul><li>FY25 borrowings: ~₹130.67 crore; Cash &amp; cash equivalents: ~₹3.36 crore → Net debt: ~₹127.31 crore</li><li>Lease liabilities (FY25): ~₹254.91 crore (Ind AS 116)</li><li>EBITDA FY25: ~₹80.49 crore (50.64% margin on ₹158.88 crore revenue)</li></ul><p>EV (ex-lease):</p><ul><li>At ₹56: EV ≈ ₹732.53 cr → EV/Revenue ≈ 4.61x; EV/EBITDA ≈ 9.10x</li><li>At ₹61: EV ≈ ₹786.57 cr → EV/Revenue ≈ 4.95x; EV/EBITDA ≈ 9.77x</li></ul><p>EV (incl. lease liabilities):</p><ul><li>At ₹56: EV ≈ ₹987.44 cr → EV/Revenue ≈ 6.21x; EV/EBITDA ≈ 12.27x</li><li>At ₹61: EV ≈ ₹1,041.48 cr → EV/Revenue ≈ 6.56x; EV/EBITDA ≈ 12.94x</li></ul><p>Pro forma (ex-lease) after planned ₹35.00 cr debt repayment from Net Proceeds:</p><ul><li>At ₹56: EV ≈ ₹697.53 cr → EV/Revenue ≈ 4.39x; EV/EBITDA ≈ 8.67x</li><li>At ₹61: EV ≈ ₹751.57 cr → EV/Revenue ≈ 4.73x; EV/EBITDA ≈ 9.34x</li></ul><h3>Peer comparison snapshot (FY25 basis, from RHP)</h3><p>Listed peers: Awfis Space Solutions, Smartworks Coworking Spaces, Indiqube Spaces</p><ul><li><strong>Scale</strong>: DevX (₹158.88 cr revenue) vs Awfis (₹1,207.5 cr), Smartworks (₹1,374.1 cr), Indiqube (₹1,059.3 cr) → DevX ~1/7th to 1/9th the scale</li><li><strong>EBITDA margin</strong>: DevX 50.64% vs Awfis 35.40%, Smartworks 62.39%, Indiqube 58.20% → DevX in line with efficient peers</li><li><strong>Revenue CAGR (FY23–25)</strong>: DevX 50.75% vs Awfis 48.81%, Smartworks 38.98%, Indiqube 35.17% → DevX shows fastest growth</li><li><strong>Occupancy</strong>: DevX 87.61% vs Awfis 83.04%, Smartworks 83.12%, Indiqube 85.12% → DevX leads on utilization</li><li><strong>Center count</strong>: DevX 26 centers vs Awfis 208, Smartworks 46, Indiqube 105 → DevX smallest but highest per-center productivity</li><li><strong>P/E context</strong>: Awfis posted profit (₹67.87 cr PAT), others losses; DevX modest ₹1.77 cr PAT → P/E optically high but growth trajectory strong</li></ul><p><strong>Takeaway</strong>: DevX trades at premium to revenue (EV/Rev ~4.4x–4.7x vs peers likely lower) but justified by superior margins, occupancy, and growth. Watch for scale-up execution and margin sustainability.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a7f9e5eb4368" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Upload files in FastAPI with file validation]]></title>
            <link>https://medium.com/@jayhawk24/upload-files-in-fastapi-with-file-validation-787bd1a57658?source=rss-f4423e7b8d00------2</link>
            <guid isPermaLink="false">https://medium.com/p/787bd1a57658</guid>
            <category><![CDATA[validation]]></category>
            <category><![CDATA[python]]></category>
            <category><![CDATA[fastapi]]></category>
            <category><![CDATA[life]]></category>
            <category><![CDATA[github]]></category>
            <dc:creator><![CDATA[Anubhav]]></dc:creator>
            <pubDate>Fri, 08 Sep 2023 11:35:31 GMT</pubDate>
            <atom:updated>2024-02-06T13:49:21.254Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*J5iTaBae6WbT6OIr" /><figcaption>Photo by <a href="https://unsplash.com/@viktortalashuk?utm_source=medium&amp;utm_medium=referral">Viktor Talashuk</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>File upload and validation can get tricky when it comes to FastAPI as we simply cannot use <a href="https://docs.pydantic.dev/latest/">pydantic</a> to do validations for us. Let’s see how to get this done.</p><p>First of all we need to install <a href="https://andrew-d.github.io/python-multipart/">python-multipart</a> . With a simple command</p><p>pip install python-multipart</p><p>This is because upload files are sent as form data.</p><pre>from fastapi import UploadFile<br><br>@app.post(&quot;/file&quot;)<br>def upload_file(file: UploadFile):<br>    validate_file_size_type(file)<br><br>    return {<br>        &quot;filename&quot;: file.filename,<br>        &quot;content_type&quot;: file.content_type,<br>    }</pre><p>Here I have a simple function which takes a file as a parameter. Since we have typed it as UploadFile, the request body has to be sent as multipart/form-data. Now let&#39;s check out our validate_file_size_type function.</p><pre>from fastapi import HTTPException, status<br>from typing import IO<br>import filetype<br><br><br>def validate_file_size_type(file: IO):<br>    FILE_SIZE = 2097152 # 2MB<br><br>    accepted_file_types = [&quot;image/png&quot;, &quot;image/jpeg&quot;, &quot;image/jpg&quot;, &quot;image/heic&quot;, &quot;image/heif&quot;, &quot;image/heics&quot;, &quot;png&quot;,<br>                          &quot;jpeg&quot;, &quot;jpg&quot;, &quot;heic&quot;, &quot;heif&quot;, &quot;heics&quot; <br>                          ] <br>    file_info = filetype.guess(file.file)<br>    if file_info is None:<br>        raise HTTPException(<br>            status_code=status.HTTP_415_UNSUPPORTED_MEDIA_TYPE,<br>            detail=&quot;Unable to determine file type&quot;,<br>        )<br><br>    detected_content_type = file_info.extension.lower()<br><br>    if (<br>        file.content_type not in accepted_file_types<br>        or detected_content_type not in accepted_file_types<br>    ):<br>        raise HTTPException(<br>            status_code=status.HTTP_415_UNSUPPORTED_MEDIA_TYPE,<br>            detail=&quot;Unsupported file type&quot;,<br>        )<br><br>    real_file_size = 0<br>    for chunk in file.file:<br>        real_file_size += len(chunk)<br>        if real_file_size &gt; FILE_SIZE:<br>            raise HTTPException(status_code=status.HTTP_413_REQUEST_ENTITY_TOO_LARGE, detail=&quot;Too large&quot;)</pre><p>In this function, we are validating if the file is of type image. Note that we are not just checking the extension of the file name as it can be changed. You can change the list for the expected file type like application/json for JSON files.</p><p>So, here’s the thing, a file is not completely sent to the server and received by your FastAPI app before the code in the path operation starts to execute.</p><p>So, you don’t have an actual way of knowing the actual size of the file before reading it.</p><p>You can check out this GitHub discussion for deeper understanding <a href="https://github.com/tiangolo/fastapi/issues/362">https://github.com/tiangolo/fastapi/issues/362</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=787bd1a57658" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How to implement pagination in FastAPI feat. SQLAlchemy]]></title>
            <link>https://medium.com/@jayhawk24/how-to-implement-pagination-in-fastapi-feat-sqlalchemy-ec284e294254?source=rss-f4423e7b8d00------2</link>
            <guid isPermaLink="false">https://medium.com/p/ec284e294254</guid>
            <category><![CDATA[pagination]]></category>
            <category><![CDATA[python]]></category>
            <category><![CDATA[sqlalchemy]]></category>
            <category><![CDATA[fastapi]]></category>
            <dc:creator><![CDATA[Anubhav]]></dc:creator>
            <pubDate>Sat, 18 Mar 2023 09:13:46 GMT</pubDate>
            <atom:updated>2023-03-18T09:15:14.913Z</atom:updated>
            <content:encoded><![CDATA[<p>In this blog, I will explain how we can implement custom pagination in FastAPI without any external packages.</p><pre>from typing import Generic, List, TypeVar<br><br>from pydantic import BaseModel, conint<br>from pydantic.generics import GenericModel<br><br><br>class PageParams(BaseModel):<br>    page: conint(ge=1) = 1<br>    size: conint(ge=1, le=100) = 10<br><br><br>T = TypeVar(&quot;T&quot;)<br><br><br>class PagedResponseSchema(GenericModel, Generic[T]):<br>    &quot;&quot;&quot;Response schema for any paged API.&quot;&quot;&quot;<br><br>    total: int<br>    page: int<br>    size: int<br>    results: List[T]</pre><p>First, we declare the pydantic schema for request and response. Here conint (constrained int) is used which does validation checks.</p><p>PagedResponseSchema is a generic pydantic model which takes any other pydantic model and puts it in results values as a list.</p><pre>from fastapi import FastAPI, Depends, Request, Query<br>from pagination import PagedResponseSchema, PageParams, paginate<br>from pydantic import BaseModel<br>from sqlalchemy.orm import Session<br>from db import get_db<br>from user import User<br><br>app = FastAPI()<br><br>class UserSchema(BaseModel):<br>    id: int<br>    name: str<br><br>    class Config:<br>        orm_mode = True<br><br>@app.get(&quot;/users&quot;, response_model=PagedResponseSchema[UserSchema])<br>def get_users(request: Request, page_params: PageParams = Depends(), db: Session = Depends(get_db)):<br><br>    # # Add 1000 users to the database<br><br>    # for i in range(1000):<br>    #     db.add(User(id=i, name=f&quot;User {i}&quot;))<br>    <br>    # db.commit()<br><br>    query = db.query(User)<br><br>    return paginate(page_params, query, UserSchema)</pre><p>Next we have our <a href="http://main.py">main.py</a> file where our fastAPI server will be running.</p><p>In UserSchema we have added orm_mode: True which will take sql ORM model and converts it into pydantic schema. It also does many fancy things you can <a href="https://docs.pydantic.dev/usage/models/#orm-mode-aka-arbitrary-class-instances">read in docs</a></p><p>After that one key point to note is how the page_params is declared. This way it is interpreted as query params and not as request body.</p><p>Now time for our special sauce paginate function.</p><pre>def paginate(page_params: PageParams, query, ResponseSchema: BaseModel) -&gt; PagedResponseSchema[T]:<br>    &quot;&quot;&quot;Paginate the query.&quot;&quot;&quot;<br><br>    paginated_query = query.offset((page_params.page - 1) * page_params.size).limit(page_params.size).all()<br><br>    return PagedResponseSchema(<br>        total=query.count(),<br>        page=page_params.page,<br>        size=page_params.size,<br>        results=[ResponseSchema.from_orm(item) for item in paginated_query],<br>    )</pre><p>This function is not that trivial, it just takes params and query and then adds offset and limit to that query. Now since ORM does lazy loading the call to the database has not happened yet that’s why we can add limit and offset values.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*gEOs8yTM1ZdnQp0j" /></figure><p>And voila! Your performant pagination API is ready.</p><p><em>You can find sample code on github </em><a href="https://github.com/jayhawk24/pagination-fastapi"><em>https://github.com/jayhawk24/pagination-fastapi</em></a><em> . Feel free to follow me on github</em></p><p><em>Originally published at </em><a href="https://jayhawk24.hashnode.dev/how-to-implement-pagination-in-fastapi-feat-sqlalchemy"><em>https://jayhawk24.hashnode.dev</em></a><em>.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ec284e294254" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How to auto fix lint errors in a Pull Request (isort & black)]]></title>
            <link>https://medium.com/@jayhawk24/how-to-auto-fix-lint-errors-in-a-pull-request-isort-black-f90d6e1a3da9?source=rss-f4423e7b8d00------2</link>
            <guid isPermaLink="false">https://medium.com/p/f90d6e1a3da9</guid>
            <category><![CDATA[black]]></category>
            <category><![CDATA[github-actions]]></category>
            <category><![CDATA[ci-cd-pipeline]]></category>
            <category><![CDATA[linter]]></category>
            <category><![CDATA[python]]></category>
            <dc:creator><![CDATA[Anubhav]]></dc:creator>
            <pubDate>Wed, 08 Feb 2023 11:26:15 GMT</pubDate>
            <atom:updated>2023-02-08T11:26:15.982Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*OEPf8g3u5uhYfhwr" /><figcaption>Photo by <a href="https://unsplash.com/@afgprogrammer?utm_source=medium&amp;utm_medium=referral">Mohammad Rahmani</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>Auto fix lint errors like spacing, sorting imports and much more, let Github Actions create a commit for you fixing them.</p><p>If you want to fix lint errors running on CI you can easily commit all changes that the linter has made.</p><p>In this example, I will be using <strong>black</strong> and <strong>isort</strong> to lint a python repo and sort the imports in the correct order also removing any unused imports.</p><pre>name: Lint<br><br>on:<br>  pull_request:<br>    branches: [&#39;*&#39;]<br><br>jobs:<br>  run-linters:<br>    name: Run linters<br>    runs-on: ubuntu-latest<br><br>    steps:<br>      - name: Check out Git repository<br>        uses: actions/checkout@v2<br><br>      - name: Set up Python<br>        uses: actions/setup-python@v1<br>        with:<br>          python-version: 3.8<br><br>      - name: Install Python dependencies and run linters<br>        # Here you can use your own linter commands<br>        run: |<br>          pip install black isort<br>          black .<br>          isort --profile black --sg=&quot;app/alembic/**&quot;  .<br><br>      - name: Run linters<br>        uses: stefanzweifel/git-auto-commit-action@v4<br>        with:<br>          commit_message: &#39;Applied automatic fixes from linters&#39;<br>          github_token: ${{ secrets.GITHUB_TOKEN }}</pre><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f90d6e1a3da9" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Automatically apply to jobs with this python bot.]]></title>
            <link>https://medium.com/@jayhawk24/automatically-apply-to-jobs-with-this-python-bot-167b96065c04?source=rss-f4423e7b8d00------2</link>
            <guid isPermaLink="false">https://medium.com/p/167b96065c04</guid>
            <category><![CDATA[jobs]]></category>
            <category><![CDATA[python]]></category>
            <category><![CDATA[selenium]]></category>
            <category><![CDATA[hiring]]></category>
            <category><![CDATA[bots]]></category>
            <dc:creator><![CDATA[Anubhav]]></dc:creator>
            <pubDate>Sat, 28 Jan 2023 12:25:57 GMT</pubDate>
            <atom:updated>2023-01-28T13:30:46.694Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/500/1*q4Jug_YPKOvFpDtLq6smng.png" /></figure><p>Applying to jobs can be a tedious job why not let a bot handle it?</p><p>I personally love <a href="http://instahyre.com/">Instahyre</a> as they don’t ask any follow-up questions and it’s just one click to apply.</p><p>So let’s use python to do this instead.</p><pre>from selenium import webdriver<br>from selenium.webdriver.common.by import By<br>import time<br><br><br># configure your email and password here<br>email = &quot;youremail@example.com&quot;<br>password = &quot;yourpass&quot;<br><br># create a new browser instance<br>driver = webdriver.Firefox()<br><br># navigate to the website<br>driver.get(&quot;https://www.instahyre.com/&quot;)<br><br># locate the login button and click on it<br>login_button = driver.find_element(By.XPATH, &quot;//a[@href=&#39;/login/&#39;]&quot;)<br>login_button.click()<br><br># locate the email and password fields and enter the values<br>email_field = driver.find_element(By.ID, &quot;email&quot;)<br>email_field.send_keys(email)<br>password_field = driver.find_element(By.ID, &quot;password&quot;)<br>password_field.send_keys(password)<br><br># locate the submit button and click on it<br>submit_button = driver.find_element(By.XPATH, &quot;//button[@type=&#39;submit&#39;]&quot;)<br>submit_button.click()<br><br># wait for 3 seconds after login<br>time.sleep(3)<br><br># locate the first view button and click on it<br>view_button = driver.find_elements(By.XPATH, &quot;//button[contains(text(), &#39;View&#39;)]&quot;)[0]<br>view_button.click()<br><br># wait for 3 seconds<br>time.sleep(3)<br><br># number of applications to be sent<br>t = 1000<br>while t &gt; 0:<br>    try:<br>        # locate the apply button and click on it<br>        apply_button = driver.find_element(By.XPATH, &quot;//button[contains(text(), &#39;Apply&#39;)]&quot;)<br>        apply_button.click()<br>    except:<br>        print(&quot;Apply button not found.&quot;)<br>    # wait for 1 seconds<br>    t -= 1<br>    time.sleep(1)<br><br>driver.quit()</pre><p>In order to run this script all you need is to install python</p><p><strong>Create a virtual environment and set it up</strong></p><pre>python3 -m venv env<br>source env/bin/activate</pre><p><strong>then use pip to install the requirements with</strong></p><pre>pip install -r requirements.txt</pre><pre>#requirements.txt file<br><br>async-generator==1.10<br>attrs==22.2.0<br>black==22.12.0<br>certifi==2022.12.7<br>cffi==1.15.1<br>click==8.1.3<br>colorama==0.4.6<br>exceptiongroup==1.1.0<br>h11==0.14.0<br>idna==3.4<br>mypy-extensions==0.4.3<br>outcome==1.2.0<br>pathspec==0.10.3<br>platformdirs==2.6.2<br>pycparser==2.21<br>PySocks==1.7.1<br>selenium==4.7.2<br>sniffio==1.3.0<br>sortedcontainers==2.4.0<br>tomli==2.0.1<br>trio==0.22.0<br>trio-websocket==0.9.2<br>urllib3==1.26.14<br>wsproto==1.2.0</pre><p>Now all you need to do is to enter your email and password and run the script</p><pre>python ./main.py</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/1*bPDAM6oSAfxTaGXQSBvspA.gif" /><figcaption>Python goes brrrrrrr</figcaption></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=167b96065c04" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Manipulate child state from parent in React.]]></title>
            <link>https://medium.com/@jayhawk24/manipulate-child-state-from-parent-in-react-4fc4a3edd38c?source=rss-f4423e7b8d00------2</link>
            <guid isPermaLink="false">https://medium.com/p/4fc4a3edd38c</guid>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[react-hook]]></category>
            <category><![CDATA[react-refs]]></category>
            <category><![CDATA[react]]></category>
            <dc:creator><![CDATA[Anubhav]]></dc:creator>
            <pubDate>Sun, 08 Jan 2023 14:23:54 GMT</pubDate>
            <atom:updated>2023-01-08T14:23:54.880Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*FJWGrwYXlNUzMIUD" /></figure><p>Using refs we can invoke methods of child components from parent in both class components as well as in functional components. This is just a workaround, recommended way is to lift the state up to parent then pass it through props to child component or with context API.</p><p>Let’s use a simple example of a counter.</p><pre>import React, { useState } from &quot;react&quot;;<br><br>const Child = () =&gt; {<br>  const [count, setCount] = useState(0);<br><br>  return &lt;div&gt;Child counter {count}&lt;/div&gt;;<br>};<br><br>export default Child;</pre><p>And our Parent component looks like this where it has a button and renders the child component as well.</p><pre>const Parent = () =&gt; {<br>  const handleUpdate = () =&gt; {};<br>  return (<br>    &lt;div&gt;<br>      &lt;h1&gt;Parent&lt;/h1&gt;<br>      &lt;Child /&gt;<br>      &lt;button onClick={handleUpdate}&gt; Update Count &lt;/button&gt;<br>    &lt;/div&gt;<br>  );<br>};</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/809/1*_pXvkwfU87Q1DsTQ7CJr7g.png" /><figcaption>App UI</figcaption></figure><p>Now on button click we want on increase the count in child component. We can do this using refs. Let’s modify our child component first.</p><pre>const Child = forwardRef((props, ref) =&gt; {<br>  const [count, setCount] = useState(0);<br><br>  useImperativeHandle(ref, () =&gt; ({<br>    handleInc() {<br>      setCount(count + 1);<br>    }<br>  }));<br><br>  return &lt;div&gt;Child counter {count}&lt;/div&gt;;<br>});<br><br>export default Child;</pre><blockquote>React.forwardRef creates a React component that forwards the <a href="https://reactjs.org/docs/refs-and-the-dom.html">ref</a> attribute it receives to another component below in the tree.</blockquote><blockquote>useImperativeHandle customizes the instance value that is exposed to parent components when using ref. As always, imperative code using refs should be avoided in most cases. useImperativeHandle should be used with <a href="https://reactjs.org/docs/react-api.html#reactforwardref">forwardRef</a></blockquote><p>Now in parent component we just have to create a ref and pass it to child component as props.</p><pre>const Parent = () =&gt; {<br>  const childRef = createRef();<br><br>  return (<br>    &lt;div&gt;<br>      &lt;h1&gt;Parent&lt;/h1&gt;<br>      &lt;Child ref={childRef} /&gt;<br>      &lt;button onClick={() =&gt; childRef.current.handleInc()}&gt;Update Count&lt;/button&gt;<br>    &lt;/div&gt;<br>  );<br>};</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/1*X69dTajGmovXepqZNgBN5g.gif" /><figcaption>And it’s done.</figcaption></figure><p>Another pattern with class components we can use this in child components.</p><pre>class Child extends Component {<br>  constructor() {<br>    super();<br>    this.state = {<br>      count: 0<br>    };<br>    this.handleInc = this.handleInc.bind(this);<br>  }<br><br>  handleInc() {<br>    this.setState({ count: this.state.count + 1 });<br>  }<br><br>  render() {<br>    return &lt;div&gt;Count: {this.state.count}&lt;/div&gt;;<br>  }<br>}</pre><p>If you want to play around <a href="https://codesandbox.io/s/silly-montalcini-1iimot?file=/src/Parent.js">https://codesandbox.io/s/silly-montalcini-1iimot</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=4fc4a3edd38c" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>