I'm encountering an issue with my Textarea component that handles Markdown headers:
type TextareaProps = {
initValue: string;
style?: StyleProp<TextStyle>;
onChange?: (value: string) => void;
};
type OnChangeFun = NativeSyntheticEvent<TextInputChangeEventData>;
const Textarea = ({initValue, style, onChange = () => {}}: TextareaProps) => {
const [value, setValue] = useState<string>(initValue);
const changeHandler = ({nativeEvent: {text}}: OnChangeFun) => {
setValue(text);
onChange(text);
};
return (
<TextInput
style={[styles.textarea, style]}
multiline
onChange={changeHandler}>
<Text>
{value.split('\n').map((line, index) => {
const style = line.match(/^#/) && styles.header;
return (
<Fragment key={`${index}-${line}`}>
<Text style={style} >{ line }</Text>
{"\n"}
</Fragment>
);
})}
</Text>
</TextInput>
);
};
The challenge is that whenever I type a character, the cursor moves two characters. And if it's the last character in a line, it jumps to the next line.
In an attempt to address this, I've implemented controlled selection:
const Textarea = ({initValue, style, onChange = () => {}}: TextareaProps) => {
const [value, setValue] = useState<string>(initValue);
const [selection, setSelection] = useState<Selection>({
start: 0,
end: 0
});
useEffect(() => {
setSelection(({start, end}) => {
if (start === end) {
start += 1;
end = start;
}
return { start, end };
});
}, [value]);
const changeHandler = ({nativeEvent: {text}}: OnChangeFun) => {
setValue(text);
onChange(text);
};
const onSelection = ({ nativeEvent: { selection }}: OnSelectionFun) => {
setSelection(selection);
};
return (
<TextInput
selection={selection}
style={[styles.textarea, style]}
multiline
onSelectionChange={onSelection}
onChange={changeHandler}>
<Text>
{value.split('\n').map((line, index) => {
const style = line.match(/^#/) && styles.header;
return (
<Fragment key={`${index}-${line}`}>
<Text style={style} >{ line }</Text>
<Text>{"\n"}</Text>
</Fragment>
);
})}
</Text>
</TextInput>
);
};
However, this results in the entire content disappearing when typing or clicking inside the input field.
Is there a way to insert a new line after each line in the Rich Text editor and maintain the correct cursor position?
Unfortunately, I am unable to create a Snack with the code as it breaks completely in Snack, displaying [object Object]
as the output of the Textarea.