jeremybarbet / react-native-portalize

The simplest way to render anything on top of the rest.
MIT License
333 stars 22 forks source link

TextInput inside a portal is buggy #6

Open eloisp opened 3 years ago

eloisp commented 3 years ago

Hi,

I use this plugin to have a beautiful shadow (all screen) behind a bottom sheet (https://github.com/osdnk/react-native-reanimated-bottom-sheet). I have some textinput inside, but the cursor is buggy they are in the Portal.

This is the exact same issue than him : https://github.com/callstack/react-native-paper/issues/1668

He found a hack but it seems... terrible.

Any idea to correct the problem? Thank's !

jeremybarbet commented 3 years ago

Hi,

Indeed this issue is very weird. Did you try with react-native-web or react-native?

I tried it with the following:

npx create-react-native-app test
cd test
yarn start
yarn ios # other tab

App.js

import React, { useState } from 'react';
import { TextInput } from 'react-native';
import { Portal, Host } from 'react-native-portalize';

export default () => {
  const [data, setData] = useState('foo');

  return (
    <Host>
      <Portal>
        <TextInput style={{ top: 200 }} value={data} onChangeText={setData} />
      </Portal>
    </Host>
  );
};

and it works as expected. (Also, you have to use Host component and not Provider when using react-native-portalize)

Have you tried using TextInput from react-native directly instead of react-native-paper?

raifemre commented 3 years ago

this issue still exists.

eloisp commented 3 years ago

I changed my plan for my app so I no more use Portalize (use a modal instead). But for those who still have this issue, this fix it :

export const TextInputInAPortal = (props) => {
  const [value, setValue] = useState(props.value)

  useEffect(() => {
    if(value !== props.value)
      setValue(props.value)
  }, [props.value])

  const onChangeText = (text: string) => {
    setValue(text)
    props.onChangeText(text)
  }
  return React.createElement(TextInput, {...props, value, onChangeText})
}

Thank's @jeremybarbet for your work :)

AlexSmirnov9107 commented 3 years ago

I confirm the bug. I am using TextInput from react-native

hermanho commented 3 years ago

This issue also affect when input with Chinese languages. The workaround cannot solve.

Here is the demo: https://snack.expo.io/@hkhermanho/textinput-with-cjk RPReplay_Final1607016357_320

There is no problem when both TextInput are placed without Portal. RPReplay_Final1607016421_320

fermmm commented 3 years ago

I'm having the same issue

zombie6888 commented 3 years ago

The issue occurs when you use portal in component, which control input by state. As workaround, i made HOC for portal:

import React, { FC } from 'react'
import { Portal } from 'react-native-portalize'

export const withPortal = <P,>(Component: FC<P>) => (props: P) => (
  <Portal>
    <Component {...props} />
  </Portal>
)

Then, i can use it like this:

export default withPortal(ComponentWithInput)

If component, which makes textinput value updates, is inside portal it works as it should

wolfag commented 2 years ago

try this:

import React, { useState } from 'react';
import { TextInput } from 'react-native';
import { Portal, Host } from 'react-native-portalize';

export default () => {
  const [data, setData] = useState('foo');

  return (
    <Host>
      <Portal>
        <TextInput style={{ top: 200 }} defaultValue={data} onChangeText={setData} />
      </Portal>
    </Host>
  );
};
JaynPan commented 2 years ago

Still encounter the same issue when using react-native-modalize

The text input glitch like @hermanho provided demo video. This issue occur while passing the state to Modalize component. Any suggestion is appreciated and thank you in advanced!

import { Portal } from 'react-native-portalize';

const QuickInstallation: FC<PrivateStackNavProps<'QuickInstallation'>> = ({ route, navigation }) => {
  const roomListModalRef = React.useRef<Modalize>();
  const [searchRoom, setSearchRoom] = useState('');

  const openRoomListModal = () => {
    roomListModalRef.current?.open();
  };

  const closeRoomListModal = () => {
    roomListModalRef.current?.close();
  };

  const selectRoomOption = ({ id, name }: RoomDto) => {
    setSelectedRoom({ id, name });
    closeRoomListModal();
  };

  return (
    <Layout>
      <Portal>
        <Modalize
          ref={roomListModalRef}
          modalHeight={modalHeight}
          tapGestureEnabled={false}
          HeaderComponent={
            <ModalHeader title="安裝教室" onPressCloseButton={closeRoomListModal}>
              <SearchBar placeholder="搜尋教室名稱" onChangeText={(value) => setSearchRoom(value)} value={searchRoom} />
            </ModalHeader>
          }
        />
      </Portal>
    </Layout>
  );
};
bombillazo commented 1 year ago

This is still an issue. When selecting an input that opens the keyboard outside the modal, then selecting an input inside the portal that opens the keyboard and you close the keyboard, the whole layout gets screwed up.

mertcankose commented 9 months ago

if you still have an problem with multiline prop use defaultValue={text} instead of value={text}

convurt commented 9 months ago

OMG @mertcankose how was that so simple? Thank you, fixed my problem.