Home > Enterprise >  Problem when a component is replaced based on a state
Problem when a component is replaced based on a state

Time:12-07

I'm a beginner to React/Preact and I'm facing to a problem that I don't understand. I have radio inputs to choose a component (FormInput) to display according to a state:

{
this.state.radio === true ?
    <FormInput id="keyword" name="keyword" required={true}>Keyword</FormInput> :
    <FormInput id="url" name="url" required={true} placeholder="https://" pattern={'https://.*'} >URL</FormInput>
}

keyword is displayed first, then I display url and a switch back to keyword. The render of the HTML is correct but when I switch back to the keyword input, the props of this input is the props of the url input.

But if I change the html rendering by adding <></> for example, I don't have the problem:

{
this.state.radio === true ?
    <><FormInput id="keyword" name="keyword" required={true}>Keyword</FormInput></> :
    <FormInput id="url" name="url" required={true} placeholder="https://" pattern={'https://.*'} >URL</FormInput>
}

What am I doing wrong please ? Thank you.

Edit: FormInput code:

export function FormInput(props: InputProps) {
    const {
        id,
        name,
        value = '',
        required = false,
        disabled = false,
        readonly = false,
        type = 'text',
        autocomplete = 'off',
        pattern,
        children,
        placeholder = children,
        title = '',
        setRef,
        handleValueChange = () => {}
    } = props;
    let {classInputName = '', classGroupName = ''} = props;

    classInputName = classNames('form-control', classInputName)
    classGroupName = classNames('form-group', classGroupName)

    let inputDom = setRef;
    if(!setRef){
        inputDom = useRef(null) as Ref<HTMLInputElement>;
    }

    const onInput = useCallback((e: any) => {
        handleValueChange(name, e.target.value,);
    }, []);
    
    return (
        <div class={classGroupName}>
            {children ?
                <label for={id}>{children}{required ? <span title="Required" rel="tooltip" class="required badge badge-empty rounded-circle ml-2"/> : ''}</label>
                : <></>}
            <input
                ref={inputDom}
                {...{id, name, type, required, disabled, readonly, pattern, onInput, placeholder, value, autocomplete, title}}
                class={classInputName}
            />
        </div>
    )
}

CodePudding user response:

when you switch FormInput component, React will try to re-use the old one for performance, so it will keep the old one's props, when you use <></> to warp the keyword FormInput, react knows the sibling components are different, so it won't re-use your old component, you can try to add different key prop to FormInput component, like this to tell react they are different:

{
this.state.radio === true ?
    <FormInput key="keyword" id="keyword" name="keyword" required={true}>Keyword</FormInput> :
    <FormInput key="url" id="url" name="url" required={true} placeholder="https://" pattern={'https://.*'} >URL</FormInput>
}

further imformation: https://reactjs.org/docs/lists-and-keys.html#gatsby-focus-wrapper

  • Related