Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

js2-jsx-mode - Issue with intendation after code block in jsx #490

Closed
kbrah opened this issue Mar 20, 2018 · 6 comments
Closed

js2-jsx-mode - Issue with intendation after code block in jsx #490

kbrah opened this issue Mar 20, 2018 · 6 comments

Comments

@kbrah
Copy link

kbrah commented Mar 20, 2018

I'm having a problem with intendation in js2-jsx-mode. The problem occurs when there is jsx next to a code block

expected:

<App>
    <div>
        {variable1}
        <Component/>
    </div>
</App>

actual behavior:

<App>
    <div>
        {variable1}
        <Component/>
</div>
</App>

I'm using spacemacs and emacs v25.3 on Windows.
Is this a known issue or am I doing something wrong? (I'm fairly new to the emacs world)

@dgutov
Copy link
Collaborator

dgutov commented Mar 20, 2018

Indentation problems with JSX are known and expected, and so far there are more reports than people interested in fixing them (sorry).

Also see https://github.com/mooz/js2-mode/#bugs

@kirubakaran
Copy link

kirubakaran commented May 7, 2018

@kbrah I've found that wrapping the contents of the {} expression in () works most of the time. I'm trying to help fix the indentation issue though. So can you please reproduce the issue in a separate file and share that with me? ie, if you put the example you have shared above in a separate file, does it indent that way still? It doesn't seem to for me. So I'm wondering what other surrounding code could have triggered that. Thanks!

@wyuenho
Copy link
Contributor

wyuenho commented May 16, 2018

js-mode 's js-jsx-indent-line was originally implemented in this project and later pushed upstream. I think trying to fix it without looking at js2-mode's AST is just hopeless as the heuristics is super brittle. I've fixed this issue and a number of annoyances in rjsx-mode, please check it out there.

P.S. @dgutov have you thought about removing E4X from js2-mode and merging js2-mode and rjsx-mode ?

@steinarb
Copy link

steinarb commented Aug 2, 2018

I'm seeing this with rjsx-mode 20180625.58 which pulls in js2-mode 20180605.1425 (from melpa) and I still see this issue every time I use a map on an array to generate a list.

Eg. this:

return (
    <div>
        <form onSubmit={ e => { e.preventDefault(); }}>
            <div className="container">
                <div className="row">
                    <div className="col">
                        <label htmlFor="username">Velg jobb:</label>
                    </div>
                    <div className="col-xs">
                        <select onChange={(event) => onJobtypeFieldChange(event.target.value, jobtypesMap, account, performedjob)} value={performedjob.transactionName}>
                            {jobtypes.map((val) => <option key={val.id}>{val.transactionTypeName}</option>)}
                        </select>
                    </div>
                </div>
                ... 

becomes this if I reindent

return (
    <div>
        <form onSubmit={ e => { e.preventDefault(); }}>
            <div className="container">
                <div className="row">
                    <div className="col">
                        <label htmlFor="username">Velg jobb:</label>
                    </div>
                    <div className="col-xs">
                        <select onChange={(event) => onJobtypeFieldChange(event.target.value, jobtypesMap, account, performedjob)} value={performedjob.transactionName}>
                            {jobtypes.map((val) => <option key={val.id}>{val.transactionTypeName}</option>)}
    </select>
        </div>
        </div>
        ...

And this

return (
    <div>
        <div className="table-responsive table-sm table-striped">
            <table className="table">
                <tbody>
                    {jobs.map((job) =>
                         <tr key={job.id}>
                             <td>{job.transactionTime}</td>
                             <td>{job.name}</td>
                             <td>{job.transactionAmount}</td>
                             <td><input type="checkbox" checked={job.paidOut}/></td>
                         </tr>
                )}
                </tbody>
            </table>
        </div>
        <br/>
        <br/>
        <button onClick={() => onLogout()}>Logout</button>
    </div>
);

becomes this if I reindent

return (
    <div>
        <div className="table-responsive table-sm table-striped">
            <table className="table">
                <tbody>
                    {jobs.map((job) =>
                              <tr key={job.id}>
                                      <td>{job.transactionTime}</td>
                                          <td>{job.name}</td>
                                              <td>{job.transactionAmount}</td>
                                                  <td><input type="checkbox" checked={job.paidOut}/></td>
                                  </tr>
                             )}
    </tbody>
        </table>
        </div>
        <br/>
        <br/>
        <button onClick={() => onLogout()}>Logout</button>
        </div>
);

Is this something that would be fixed by the above commits and will be available in a later release?

Is there a workaround/practice that would avoid this issue?

Thanks!

@steinarb
Copy link

steinarb commented Aug 8, 2018

I've figured out that the fat-arrow functions are the culprit.

If I remove the fat-arrow functions, formatting is back to normal (but of course, the resulting code doesn't work...:-) ).

And I've found a workaround: turning the problem spots into react Components.

Curiously none of these components have formatting problems. Her's an example component that formats OK:

import React from 'react';

const Accounts = ({id, className, accounts, accountsMap, account, paymenttype, onAccountsFieldChange }) => (
    <select id={id} className={className} onChange={(event) => onAccountsFieldChange(event.target.value, accountsMap, paymenttype)} value={account.fullName}>
        {accounts.map((val) => <option key={val.accountId}>{val.fullName}</option>)}
    </select>
);

export default Accounts;

@wyuenho
Copy link
Contributor

wyuenho commented Aug 8, 2018

The identation PR hasn't been merged yet.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants