MUI Textfield multiline by state (lost focus) - reactjs

I'm solving a problem regarding setting up a multi-line input after clicking on it. (in default is it single line) I have created a state that I set to true on the onFocus event (I set it to false on the onBlur event). The problem is that after clicking, I immediately lose focus of the input and have to click again. Is there any solution for this?
export default function App() {
const [focus, setFocus] = React.useState(false);
return (
<TextField
type="text"
value="lollec asda sd asd as das "
onFocus={() => setFocus(true)}
onBlur={() => setFocus(false)}
multiline={focus}
rows={3}
/>
);
}
Demo: https://codesandbox.io/s/hardcore-night-vhep1?file=/src/App.js

You can accomplish your described behavior by changing...
multiline={focus}
rows={3}
to...
multiline
rows={focus ? 3 : 1}
However, this introduces a scrollbar on the input when it's not focused. Additionally, clicking on the input will focus your cursor on the first line of text (where you clicked). You probably want the cursor to focus at the end of the text.
If you're fine with the cursor being on the first line, then I would just add some styles to hide the scrollbar.
If not, you're going to need to manage a ref for the input and specifically call ref.current.focus(). Typically, this would focus at the beginning of the text, though, so you'll need to take extra steps to ensure focus is at the end. Check out this question for help with that: Send cursor to the end of input value in React

Related

How to change the value of hidden text input box when select menu option is changed

I want to change the existing value in a hidden text input box (automatically when the box is closed) to an empty string ('') when the user chooses one of the drop down menu selections. The problem is that I can close the component with the right menu selection, but the value does not change to an empty string until I click the button a second time. Then the value becomes an empty string and I get the correct information.
I originally based the approach to that of form data being passed to/from the parent and that does not seem to work for this component. I tried using a setState() function, however, this either didn't take or I did not implement correctly. All state has been set and all other components move data around as they're supposed to.
This is the parent component that sends/receives the information from the . The "cost={dailyTransportationCost}" is supposed to send the new value to the child.
<DailyTransportationCost
cost={dailyTransportationCost}
handleTransportationCost={e => setDailyTransportationCost(e.target.value)}
/>
This is the component that needs to change to an empty string when it's closed based on the menu option (separate component)
const DailyTransportationCost = ({ cost, handleTransportationCost }) => {
return (
<div className={`${styles.containerTransportationCost}`}>
<label className={`${styles.containerLabel}`} htmlFor='dailyTransportationCost'>Daily Cost</label>
<input className={`${styles.containerInput}`}
placeholder='0.00'
id='dailyTransportationCost'
type='number'
value={cost.dailyTransportationCost}
onChange={handleTransportationCost}
/>
</div>
);
};
Thank you for your help. I've been banging around on this for a couple of days. Any suggestions will be appreciated.
me again...
I figured it out. It was a simple useEffect() and everything worked remarkably well. Just want to thank anyone who might have stopped by.
Cheers!

Updating a state array while avoid rerenders in React

I'm building a project in react native. I have a dynamic list of players, that I want the user to be able to edit.
const [players, setPlayers] = useState(['']);
function addPlayer() {
setPlayers([...players, '']);
}
...
<List>
{ players.map(player => (
<MyInput ...>
)}
</List>
What I want to achieve is this:
User enters name
User presses enter
We call addPlayer which adds a player
New input appears and gets focused on (by other functions).
What I get is this:
User enters name
User presses enter
We call addPlayer which adds a player
The Keyboard starts closing for a split second and then opens back up when the new input appears.
I have set blurOnSubmit to false on my inputs. In my opinion what happens is that the list gets rerendered, causing the keyboard to dismiss itself. Then when the setPlayers finishes executing (it's async), the focus function gets called
useEffect(() => {
if (lastRef.current) {
lastRef.current.focus();
}
}, [players]);
What is the best way to stop the list from rerendering so that the keyboard can stay open the whole time ? Thanks !
In the end I cheated, I added an input that’s sitting right outside the list. I can control whether it’s shown or not, it’s content, as well as it’s color with other state variables.
That way when a player is added the list rerenders but doesn’t affect my input, and my keyboard doesn’t move.
From a users POV it looks exactly the same as it did before, as if he’s editing items directly in the list.

Add an additional component as soon as user types on input

I know how to add an item based on state. When user type something on input, It generates list items based on state(mapping) like below code.
return (
<div className="App">
<input name="name" value={name} onChange={handleInput} />
<button onClick={() => handleBtn(names)}>Click Me</button>
{names.map((item) => (
<div>{item}</div>
))}
</div>
);
But I want to add one more additional component automatically as soon as user type something on input.
To add an additional component easily right after finish typing like below image (+ List Item)
Here is an example
(Additional question)
I write a function which adding a listItem component onChange event. But it adds a component every time user type text as you know.. So I guess, To add an additional component successfully, I need to know when user starts and finishes typing not to add it multiple times(like user stops for a wile and typing again). Do you guys have any idea?
You could use onBlur so when the user finishes typing and loses the focus from the input you could add the additional component.
onBlur will be called every time the field loses the focus so if you want to add the additional component only if the value of the input has been changed, then you need to check if the value was changed after the blur, and then add the new component.

React-Native TextInput prevent default on controlled input

So I use my state to control a text input, but when I input a character, I don't want the character to show up right away. This is what is happening:
1. I focus on text input
2. I type in a character.
3. The character quickly shows up in the text input.
4. The character quickly disappears and the value reverts back to the state because the state has not changed yet.
I am wondering how I can prevent the character from showing up in the first place if the state has not changed.
Here is a simple example:
state = {
myValue: 'hello'
}
changedText = value => {
//Nothing here yet
}
...
render(){
return(
<Input
value={this.state.myValue}
keyboardType="numeric"
onChangeText={this.highIntervalDurationChange}
/>
);
}
As you can see it's nothing complicated, I'm just trying to figure out a way to not have the pressed character not appear right away when it is pressed because currently it appears and reverts back to the state. (Obviously I will modify the state after I can figure out how to prevent default from happening.) I also tried setting editable to false and that just makes it so I can't edit it at all. Thanks!

Testing if something is on screen with react

I have an input field with a submit button and when someone enters something that text appears on the screen. how can I test that in react?
I know how to simulate the button click but what would the expectation be? or how would I actually be able to tell if the text is there?
You would need to use refs to check the values of input fields using React. The refs provide the hooking interface between virtual DOM element of input fields to access it values.
You scry for that input element by id or type or class. And you can access the text of that element by looking at .value
I'm not sure I understand the question... the first part of your question makes me think you want to detect when a user is typing some text in an input field, but the second part makes me think you want to automate a test, placing some text in the input and simulating click on a button, kinda confusing ...
In my last project I used that package instead of a classic input: react-contenteditable
You can hook your code to events that this component is firing:
render() {
const { selectedDbItem } = this.props
return (
<div>
<ContentEditable
onBlur={(e)=>this.onBlurField(e, 'supplier')}
className="field-value"
html={selectedDbItem ? selectedDbItem.supplier : ''}
disabled={false}
onChange={(e)=>this.onChangeField(e, 'supplier')}
onKeyDown={(e) => this.onKeyDown(e)}
/>
</div>
You can then implement the callbacks onBlur, onChange, onKeyDown (for input filtering for example ...) in the containing component.
Hope that helps

Resources