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

Can not ignore unicorn/no-null in some case #703

Closed
yoyo837 opened this issue Apr 30, 2020 · 8 comments
Closed

Can not ignore unicorn/no-null in some case #703

yoyo837 opened this issue Apr 30, 2020 · 8 comments
Assignees

Comments

@yoyo837
Copy link

yoyo837 commented Apr 30, 2020

.eslintrc.js: rules 'unicorn/no-null': 0,

code (Note the line of code marked FIXME):

// import 'core-js/stable';
// import 'regenerator-runtime/runtime';
import uniq from 'lodash/uniq';
import React from 'react';
import ReactDom from 'react-dom';
import { createStore, combineReducers, applyMiddleware, compose } from 'redux';
import { Provider } from 'react-redux';
import { createBrowserHistory } from 'history';
import { ConnectedRouter, connectRouter, routerMiddleware } from 'connected-react-router';
import createSagaMiddleware from 'redux-saga';

import modelManager, { getReducer, getSaga, SHOW, HIDE } from '@/models';
import initRequest from '@/utils/request';
import App from '@/routes/App';

const history = createBrowserHistory();

// Build the middleware for intercepting and dispatching navigation actions
const reduxRouterMiddleware = routerMiddleware(history);
const reduxSagaMiddleware = createSagaMiddleware();

// window.__REDUX_DEVTOOLS_EXTENSION__
// const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({
//   //
// }) || compose
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const connectRouterReducer = connectRouter(history);

const allModelKeys = modelManager.keys();

const injectedModels = [];
const loadModels = keys => {
  injectedModels.push(
    ...uniq(keys)
      .filter(key => !injectedModels.some(m => m.namespace === key) && allModelKeys.includes(key))
      .map(key => {
        const model = modelManager.load(key);
        if (model == null) { // **FIXME target line 1** 
          throw new Error(`[${key}]: Model load fails`);
        }
        return model.default || model;
      })
      .filter(Boolean)
  );
};

// redux 初始化默认加载的model
const initialModels = ['global', 'login', 'user', 'venue', 'datatable', 'extfield'];

loadModels(initialModels);

const createNewReducers = () => {
  const reducers = {};
  injectedModels.forEach(model => {
    reducers[model.namespace] = getReducer(model);
  });
  return combineReducers({
    ...reducers,
    loading: (state, action) => {
      switch (action.type) {
        case SHOW:
        case HIDE:
          return {
            ...state,
            effects: {
              ...state.effects,
              [action.payload.actionType]: action.type === SHOW,
            },
          };
        default:
          return state || {};
      }
    },
    router: connectRouterReducer,
  });
};

const runSaga = (keys = [], hasLoadKeys = []) => {
  injectedModels
    .filter(model => keys.includes(model.namespace) && !hasLoadKeys.includes(model.namespace))
    .forEach(model => {
      reduxSagaMiddleware.run(getSaga(model));
    });
};

const store = createStore(
  createNewReducers(),
  // preloadedState
  {
    loading: {
      effects: {},
    },
  },
  composeEnhancers(
    applyMiddleware(
      reduxRouterMiddleware,
      // promiseMiddleware
      // eslint-disable-next-line unicorn/consistent-function-scoping
      () => next => action => {
        const { type } = action;
        if (typeof type === 'string') {
          const [namespace, effectName] = type.split('/');
          // model.effects 的一定都是 effect
          if (
            injectedModels
              .filter(model => model.namespace === namespace)
              .some(model => model.effects && model.effects[effectName])
          ) {
            return new Promise((resolve, reject) => {
              next({
                ...action,
                _resolve: resolve,
                _reject: reject,
              });
            });
          }
        }
        return Promise.resolve(next(action));
      },
      reduxSagaMiddleware
    )
  )
);

initRequest(store.dispatch, store);

runSaga(initialModels, []);

const appManager = {
  injectModel: model => {
    if (model == null || model.length === 0) { // **FIXME target line 2**
      return;
    }
    const hasLoadKeys = injectedModels.map(m => m.namespace);
    loadModels(model);
    store.replaceReducer(createNewReducers());
    runSaga(model, hasLoadKeys);
  },
};

ReactDom.render(
  <Provider store={store}>
    <ConnectedRouter history={history}>
      <App app={appManager} />
    </ConnectedRouter>
  </Provider>,
  // eslint-disable-next-line unicorn/prefer-query-selector
  document.getElementById('root')
);

It report

image

If I fix any one error, the other will no longer report the error.

@papb
Copy link

papb commented Apr 30, 2020

Hi, can you try to create a smaller example? I doubt all these lines are necessary to reproduce the issue. Making it a SSCCE (also known as MCVE/reprex) will save time from maintainers and increase the odds you get a faster response.

@fisker
Copy link
Collaborator

fisker commented Apr 30, 2020

the == should be auto-fixable, if it's === should be ignored by default

@fisker
Copy link
Collaborator

fisker commented Apr 30, 2020

Question, why don't you want fixed to undefined? They are equal

@kevinoid
Copy link

One reason it might be preferable to allow == null as a special case is that the built-in eqeqeq rule has options (smart and "always", {"null": "ignore"}, used by airbnb) to allow x == null, but no similar option to allow x == undefined (see eslint/eslint#13303).

@kevinoid
Copy link

Note: x == null is a shorthand for x === null || x === undefined. I'm not advocating for or against supporting it, just came across this issue while considering it.

@fisker fisker self-assigned this Jun 1, 2020
@fisker
Copy link
Collaborator

fisker commented Jun 1, 2020

@kevinoid

Thank you for your explanation.

I think this is a bug in eslint, if (foo == null) is equals to if (foo == undefined), why allow null, but not allow undefined.

anyway, since that eqeqeq is not going to change, I'm adding an option to ignore == and != on our side.

@sindresorhus
Copy link
Owner

Per #757 (comment), this should be fixed in ESLint. Open an issue on ESLint about this.

@amakhrov
Copy link

Obviously, eslint team is not willing to make this change: eslint/eslint#13537 (comment)

So as it stands right now, the two rules (eqeqeq and no-null) are generally conflicting. Perhaps we should document it, and suggest some workarounds, if any?

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

Successfully merging a pull request may close this issue.

6 participants