基于状态替换组件时的问题
Problem when a component is replaced based on a state
我是 React/Preact 的初学者,我遇到了一个我不明白的问题。
我有无线电输入来选择一个组件(FormInput)根据状态显示:
{
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
,然后我显示 url
,然后切换回 keyword
。 HTML 的渲染是正确的,但是当我切换回 keyword
输入时,此输入的道具是 url
输入的道具。
但是,如果我通过添加 <></>
来更改 html 渲染,我就没有问题:
{
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>
}
请问我做错了什么?
谢谢。
编辑:FormInput 代码:
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>
)
}
当你切换 FormInput
组件时,React 会尝试重新使用旧的来提高性能,所以它会保留旧的 props,当你使用 <></>
包裹关键字 FormInput
, react 知道兄弟组件是不同的,所以它不会重复使用你的旧组件,你可以尝试向 FormInput
组件添加不同的 key
属性,这样告诉 react它们不同:
{
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>
}
更多信息:https://reactjs.org/docs/lists-and-keys.html#gatsby-focus-wrapper
我是 React/Preact 的初学者,我遇到了一个我不明白的问题。 我有无线电输入来选择一个组件(FormInput)根据状态显示:
{
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
,然后我显示 url
,然后切换回 keyword
。 HTML 的渲染是正确的,但是当我切换回 keyword
输入时,此输入的道具是 url
输入的道具。
但是,如果我通过添加 <></>
来更改 html 渲染,我就没有问题:
{
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>
}
请问我做错了什么? 谢谢。
编辑:FormInput 代码:
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>
)
}
当你切换 FormInput
组件时,React 会尝试重新使用旧的来提高性能,所以它会保留旧的 props,当你使用 <></>
包裹关键字 FormInput
, react 知道兄弟组件是不同的,所以它不会重复使用你的旧组件,你可以尝试向 FormInput
组件添加不同的 key
属性,这样告诉 react它们不同:
{
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>
}
更多信息:https://reactjs.org/docs/lists-and-keys.html#gatsby-focus-wrapper