React-select: onBlur doesn't work in custom component

Created on 29 May 2019  路  11Comments  路  Source: JedWatson/react-select

hi, a thousand apologies for post this here, but this crash my mind

i don't understand why onBlur doesn't work

what i expect: when i choose some checkboxes with options and click whatever at the page - select will collapse

what i get: select collabes only when i click on arrow

pls help me and sorry for my poor english

you can check code here - https://codesandbox.io/s/elegant-mestorf-7rvl8

and i past it here

```import React from "react";
import ReactDOM from "react-dom";

import Select, { components } from "react-select";

const styles = {
option: styles => ({
...styles,
backgroundColor: "#ffff",
color: "black"
})
};

const Option = props => (



);

const ValueContainer = ({ children, selectProps, ...props }) => {
console.log(selectProps);
const { getValue, hasValue } = props;
const countSelectedVal = getValue().length;
if (!hasValue) {
return (
{children}

);
}
return (
{${selectProps.messages.orderPageAnySelectPreText}: ${countSelectedVal}}

);
};

const OrderSelectMulti = ({ options, ...props }) => {
const components = { ValueContainer, Option };
const messages = {
orderPageAnySelectPreText: "Selected"
};
return (
styles={styles}
isMulti
messages={messages}
components={components}
hideSelectedOptions={false}
options={[
{ value: "Status1", label: "Status1" },
{ value: "Status2", label: "Status2" },
{ value: "Status3", label: "Status3" }
]}
placeholder="BlaBla"
{...props}
/>
);
};

const rootElement = document.getElementById("root");
ReactDOM.render(, rootElement);

issubug-unconfirmed issureviewed

Most helpful comment

I have the same issue. blur is not working and remain the blue border style on the element 'sometimes' after selecting an option if I have customized the component.
e.g. When the error prop changed from 'true' to 'false' in the following function.

const customControl = useCallback(
    ({children, ...props}) => (
      <>
        <components.Control
          {...props}
          className={classnames({
            'custom-react-select': true,
            'is-invalid': error,
          })}
        >
          {children}
        </components.Control>
        <span className="invalid-feedback">
          <ErrorMessage name={name} />
        </span>
      </>
    ),
    [name, error]
  );

All 11 comments

I have the same issue. blur is not working and remain the blue border style on the element 'sometimes' after selecting an option if I have customized the component.
e.g. When the error prop changed from 'true' to 'false' in the following function.

const customControl = useCallback(
    ({children, ...props}) => (
      <>
        <components.Control
          {...props}
          className={classnames({
            'custom-react-select': true,
            'is-invalid': error,
          })}
        >
          {children}
        </components.Control>
        <span className="invalid-feedback">
          <ErrorMessage name={name} />
        </span>
      </>
    ),
    [name, error]
  );

Hello guys, I faced with the same issue as described here. Not sure that it is exactly the same, since it is not enough info in comments. But in my case the root cause was in usage of HOC for custom component which replaced built-in. HOC creates new component each time you render it and destroy/unmount previous. So input that was created and focused on first render is replaced by completely new one - this leads to loosing focus/blur DOM state.

Similar case was asked here, it is not related to react-select, but describes the issue:
https://stackoverflow.com/questions/39120494/react-higher-order-component-forces-re-render-of-wrapped-component

My solution was not the same as you can see by link, because I still need to use HOC to make a closure for some variable. Instead I created local cache for parent component to update HOC only when variable was changed. It could be too specific for most people and probably you will be just fine to use answer from stackoverflow.

Thanks for providing some insights @fameriks.

@Flakelf and @rabbit0321 I wanted to check in and see if @fameriks's answer has helped you.

This issue will now be closed due to inactivity as there has been no response for further information. If anyone has further feedback please let me know and the issue will be re-opened.

@bladey this is still happening and has been happening for awhile, please reopen - I think @fameriks has correctly identified the issue (though I am still working it out), but this is still an issue with react-select, since imo the API should naturally preserve onFocus and onBlur without complicated workarounds.

https://github.com/JedWatson/react-select/issues/625

I'm also experiencing this issue.

In my case, I need to recompute ValueContainer each render so it can utilise the parent component's props to apply some custom formatting. This causes it to lose focus and the blur event is never fired.

i also have this issue - will it be fixed? or no? I will need to move to another library if this is not on the radar

Thanks for the feedback @j-funk and @effectivetom!

I believe the problem here is the same as in #4193.

My solution there should also be applicable here.

@fameriks has identified that it is a composition issue and not a react-select issue. Creating a new functional component in the render cycle will cause this to happen not because of how react-select works, but because of how React works. React cannot reconcile the new component from the previous component.

https://stackoverflow.com/questions/22573494/react-js-input-losing-focus-when-rerendering

To answer individual queries:
@Flakelf I have a working fork of your sandbox here:
It works as expected if you render the same valueContainer but with different children. See below and compare with your original example.

const ValueContainer = ({ children, selectProps, ...props }) => {
  console.log(selectProps);
  const { getValue, hasValue } = props;
  const countSelectedVal = getValue().length;
  return (
    <components.ValueContainer {...props}>
      {!hasValue
        ? children
        : `${selectProps.messages.orderPageAnySelectPreText}: ${countSelectedVal}`}
    </components.ValueContainer>
  );
};

@rabbit0321 I am unsure why you are running into those issues. I would likely compose it differently as putting the error message in the SelectContainer would still keep the error message and Control as sibling nodes.

One guess I would make regarding the styling issues you are seeing may be related to overriding the className passed into the control that emotion or styledComponents would have otherwise provided.

const SelectContainer = ({ children, ...props }) => (
  <component.SelectContainer {...props} >
    {children}
    {props.selectProps.error && (
        <span className="invalid-feedback">
          <ErrorMessage name={name} />
        </span>
    )}
  </component.SelectContainer>
);

const Control = ({ className, ...props }) => {
  // keep the existing className
  const newClassName = classnames(className, {
     'custom-react-select': true,
     'is-invalid': props.selectProps.error,
  });
  return  <components.Control {...props} className={newClassName} />
);

@j-funk @barrychapman @effectivetom
I would be happy to take a look at your code and see where it could be made such that the react reconciler acts in a way that you expect that it should. I've rarely shied from looking at anyone's codesandbox.

The argument being made is that react-select should handle the reconciliation of a user trying to render two different components as if it's the same instance.

The documentation could perhaps mention good practices and dangers of not being careful about this. Perhaps someone would be willing to take a look at writing a PR implementation that ensures a unique key is created for critical components like ValueContainer and Input? In the meanwhile, understand that there is some responsibility assumed for writing custom components.

I will be closing this for us to continue working through existing issues. If you have any specific questions or concerns, this can be reopened if necessary. Again, the team is very willing to work through individual code implementations so long as there is an example for us to review as the ability to compose and replace internal components also creates a lot of different use cases.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

steida picture steida  路  3Comments

yrabinov picture yrabinov  路  3Comments

pashap picture pashap  路  3Comments

sampatbadhe picture sampatbadhe  路  3Comments

mbonaci picture mbonaci  路  3Comments