0

I have a weird issue with a modal in react native (expo). My modal looks like this:

const useNewCommentModal = () => {
    const [showModal, setShowModal] = useState(false);
    const [comment, setComment] = useState('');

    const toggle = () => {
        setShowModal(!showModal);
    };

    const NewCommentModal = () => (
        <Modal visible={showModal} animationType="slide">
            <View style={[t.pX4]}>
                <TextInput
                    style={[t.bgWhite, t.p2, t.rounded, t.textLg]}
                    placeholder={'Post jouw reactie...'}
                    onChangeText={text => setComment(text)}
                    value={comment}
                />
            </View>
        </Modal>
    );

    return [toggle, NewCommentModal];
};

export default useNewCommentModal;

When I type the modal keeps reopening. When I remove this:

onChangeText={text => setComment(text)}

The problem goes away but obviously the state isn't updated anymore. How come the model keeps reopening?

--EDIT--

 const [toggleModal, NewCommentModal] = useNewCommentModal(
        'user',
        route.params.user.id
    );

<NewCommentModal />
Jamie
  • 10,302
  • 32
  • 103
  • 186
  • How are you using this? I could be wrong, but this doesn't seem like a valid use a a custom hook. It seems like it should just be a normal component. – Brian Thompson Mar 17 '20 at 20:04
  • Can you share the usage of the useNewCommentModal? – Aleksandre Javakhishvili Mar 17 '20 at 20:15
  • If this is being used as a custom hook, the component `NewCommentModal` will unmount and re-mount every render. Even if you get the toggling working as expected this doesn't seem like a desired behavior.. – Brian Thompson Mar 17 '20 at 20:16
  • @BrianThompson I've made an edit to my question. Am I using it in the wrong way? I thought hooks should be used like that? Please let me know what a better way is. – Jamie Mar 18 '20 at 10:33
  • That's the correct way to use a hook, but not a very good candidate for *being* a hook. The pattern you're trying to achieve is better suited as a normal component. The only thing you won't be able to accomplish with a normal component is keeping the `toggle` functionality coupled with it. – Brian Thompson Mar 18 '20 at 13:10
  • Custom hooks are meant to be used for reusable state and lifecycle patterns. They aren't meant to be used to make components. You may be able to get it to work in one way or another, but ultimately its not the correct use of hooks, and I wouldn't recommend it. – Brian Thompson Mar 18 '20 at 13:19
  • 1
    @BrianThompson Thanks, that makes sense :) – Jamie Mar 18 '20 at 13:34

1 Answers1

2

Every time your useNewCommentModal hook runs, it creates a new function called NewCommentModal which you then use as component <NewCommentModal /> (this part is very important). To React, every new NewCommentModal is different from a previous one (because you create new function each time and every render), React would run equality comparison between old and new NewCommentModal which will return false, so React will unmount old modal and mount a new one in it's place. That happens because you call function as component. So you should return not NewCommentModal component from your hook but a function that will render something instead (renderNewCommentModal) and call it not as a component but as a function ({renderNewCommentModal()}) instead. Or better yet, return only data from a hook, and use this data to render something in your main component

See my previous answer on this matter for more detailed explanation https://stackoverflow.com/a/60048240/8390411

Max
  • 4,473
  • 1
  • 16
  • 18
  • Thanks, when I use it like a function it works. But I'm still confused, should I do this always when I work with hooks? I thought `` was fine aswel? Thanks for helping @Max – Jamie Mar 18 '20 at 12:27
  • @Jamie for this situation hooks are not different from classic class-based components. Because even with class-based components you don't create new components directly inside `render`. You can of course use `` but only if you create it once, as a standalone component (that is, you have `const NewCommentModal = ...` outside of any component and or hook), then sure it's fine – Max Mar 18 '20 at 13:20