Ustawienie poczatkowego focusa nie działa jak bym sie spodziewała

0

Cześć,

Próbuję ustawić początkowy focus formularza na jednym z pól - a z pewnych przyczyn (mam sprawdzony formularz który działa i chciałbym jak najmniej w nim zmieniać - nie chcę używać autoFocus)

const InputForm =()=>{return(<div>  <form id='myForm' onSubmit={this.props.SubmitFunction}>
<label className= 'm-2' ></label>
<input required  id= "name" placeholder="Name..." type="text" value={this.props.name} onChange={this.props.ChangeName}/>
<label className= 'm-2'></label>
<input required type="text" id='email' placeholder="Email..." value={this.props.email} onChange={this.props.ChangeEmail}/>
</form></div>)}

Pomysł był taki, aby nadać focus w component DidMount

 
componentDidMount() {

  fetch(this.props.source)
    .then(response => response.json())
    .catch(error => console.error('Error:', error))
    .then(json => this.setState({
      staff: json.map(ob => Object.values(ob)),
      nonFilteredStaff: json.map(ob => Object.values(ob)),
    }));
    var toGetFocus =document.getElementById("name");
toGetFocus.focus();
}

Niestety uporczywie dostaję komunikat o błędzie 'toGetFocus is null'
Co jest nie tak? Zakładałam, ze w stanie DidMount już wszystko jest przypisane... stąd taka konstrukcja.
Można to jakoś na szybko poprawić?

Natomiast jeszcze dwa słowa o konstrukcji i prośba o sugestię.

Mam dwa dość podobne projekciki

W** drugim** z nich, którego fragment widzicie, jest problem z po pierwsze złapaniem w ogóle focusa na formularzu. Jeżeli już użyję focusAuto, jest problem z przejściem do drugiego pola.

W pierwszym, którego nie widzicie ale różnice opisze za chwilę, nie ma problemu z przechodzeniem między polami przez przeniesienie kursora.

Różnica jest taka, że** drugi** jest dzieckiem i dostaje wszystko w propsach, nie ma własnego stanu.

pierwszy natomiast korzysta z własnego stanu (ściśle - komponentu w którym jest zawarty; jego kod nie jest zawarty w osobnym, wywoływalnym elemencie, nie dostaje propsów)

0

React ma to do siebie, że DOM zwracany przez metodę render, a faktyczny komponent, to dwie różne rzeczy (React operuje w dużej mierze na wirtualnym drzewie DOM). Aby dostać się do konkretnego elementu powinieneś korzystać z referencji, a nie natywnych selectorów.

Link do oficjalnej dokumentacji:
https://reactjs.org/docs/refs-and-the-dom.html

0

No dobra, jestem bliska kapitulacji. Założenie jest takie, że mam stworzyć formularz zawierający dwa pola input tekstowe. Po aktywizacji focus ma być na pierwszym.

To siedzi w konstruktorze


constructor(props) {
    super(props);

this.state ={name :'',email:''}
this.handleKeyPress = this.handleKeyPress.bind(this);
this.handleChangeName =this.handleChangeName.bind(this);
this.handleChangeEmail =this.handleChangeEmail.bind(this);

Trzy funkcje, które kręcą wpisywaniem danych, trzecia przenosi focus z pierwszego pola na drugie po nacisnięciu enter.


handleChangeName(e) {
    
this.setState({
name: e.target.value
    })
   e.preventDefault();
  }
  
handleChangeEmail(e) {
this.setState({
email: e.target.value
      
    })
  e.preventDefault();
  }

handleKeyPress(e) {
    if (e.key === 'Enter') {
       
    const nextfield = document.getElementById('email')
    nextfield.focus();
    e.preventDefault();
    const previousfield = document.getElementById('name')
    
   
    }
  }

To jest renderowalny formularz


const InputForm =()=>{return(<div>  <form id='myForm' /*onSubmit={this.handleSubmitButton}*/>
<label className= 'm-2' ></label>
<input required  autoFocus id= "name"  placeholder="Name..." type="text" value={this.state.name}  value = {this.state.name} onKeyPress ={this.handleKeyPress}   onChange={this.handleChangeName}/>
<label className= 'm-2'></label>
<input required type="text" id='email'  placeholder="Email..." value={this.state.email} onChange={this.handleChangeEmail} />
</form></div>)}

a tu ten formularz jest wywoływany

<React.Fragment>
    
    {!this.props.AddUserStatus && <AddUserButton />}
    {!this.props.AddedUserMsgStatus && <AddedUserMessage />}
    {!this.props.InputFormStatus && <InputForm />}
   
</React.Fragment>)

Chodzi o to, że jeżeli użyję autoFocus jak w tekście, wpisze coś w pierwsze pole, a następnie przejdę enterem do drugiego, uda mi się tam wpisać dokładnie jedną literę, gdyż po wpisaniu pierwszej litery aktualizuje się stan i focus wraca na pierwszy element.
Sprawdziłam kilka miejsc ale wszystkie rozwiązania które znalazłam zakładają użycie na przykład dodatkowego guzika który wywoła funkcję ustawiania focusa co jest w tym wypadku niedopuszczalne - formularz ma się pokazać od razu z focusem na pierwszym polu. A potem przejść bezproblemowo na drugie.
W zasadzie ten komponent dostaje funkcje od rodzica, (to jest wycinek kodu) ale chciałabym mieć to najprościej jak się da. Poza tym próbowałam kilku mniej lub bardziej karkołomnych rozwiązań i nic z tego nie działa. No raczej nie chciałbym robić z każdego pola formularza osobnego komponentu z osobnym stanem.

0

Właściwe zamiast htmlowego autoFocus zadziała ref={input => input && input.focus()} ale to nie posuwa sprawy naprzód w tym sensie, że z następnego pola to wraca po wpisaniu jednej litery.

0
Bogaty Rycerz napisał(a):

Zrób tak: https://codesandbox.io/s/mom9jk3n7y

I to są właśnie chwile kiedy opada kopara. To działa lepei niż wszystko co wczesniej napisałam w tym temacie. Tylko... dlaczego?
Tworzysz jeden input a wyświetlają się dwa??? Powtórka z Kany Galilejskiej ???
A najważniejsze - chociaż sama już zaczynam próbować jakoś to wkomponować w resztę - jak z tego sczytać wartości - tu ewidentnie nie mają stanu - jak przypisać dwa różne placeholdery?

0

https://reactjs.org/docs/refs-and-the-dom.html#adding-a-ref-to-a-dom-element
a konkretnie:

React will assign the current property with the DOM element when the component mounts, and assign it back to null when it unmounts. ref updates happen before componentDidMount or componentDidUpdate lifecycle hooks.

Nie rozumiem o co pytasz w kontekście placeholderów. Update'owałem box.

0
Bogaty Rycerz napisał(a):

https://reactjs.org/docs/refs-and-the-dom.html#adding-a-ref-to-a-dom-element
a konkretnie:

React will assign the current property with the DOM element when the component mounts, and assign it back to null when it unmounts. ref updates happen before componentDidMount or componentDidUpdate lifecycle hooks.

Nie rozumiem o co pytasz w kontekście placeholderów. Update'owałem box.
Chodzi o to że mam mieć dwa pola z dwoma różnymi placeholderami i jakiś sposób na sczytanie wartości. Ten przykład jest z jednej strony genialny - bo działa i jest krótki a z drugiej choćbym chciała to nie rozumiem skąd tam się biorą dwa inputy.

0

W funkcji render zwracane są w dwa inputy, dlatego renderują się dwa. Spójrz dobrze na markup.
Co rozumiesz przez placeholder? W jaki sposób chciałabyś go zczytywać?

0

No tak, patrzałam patrzałam i jeden tradycyjnie drugi jako ref. Z placeholderami chodzi o to, żeby każdy z nich miał inny, tymczasem o ile dodanie placeholdera do pierwszego jest oczywiste, to do drugiego już nie. A ze sczytaniem chodzi o wpisywane wartości. Ja jestem na etapie kiedy jest oczywiste, że aby to co widać w inpucie było odświeżane z każdą wklikaną literką to musi to mieć oparcie w stanie elementu. Stąd kopara opada jak patrze na ten kod

0

Mogę wysharować Ci w trybie live edit boxa, tam jest też czat, więc będzie łatwiej wyjaśnić ewentualne wątpliwości i razem dojść do tego, czego Ci brakuje.

0

Dzięki :)
Słuchaj, ja mogę to opisać. Ten form jest częścią większej całości. Generalnie chodzi to aby oba inputy dąło się od siebie fizycznie odseparować ( na tyle, żeby wstawić między nie słowo opisu, oraz w jakiś prosty sposób pobrać wartości. I dołożyć do drugiego z nich - wewnętrznego - placeholder.
Ja do tej pory pisałam dość proste komponenty i to tak. Z zewnętrznego jeszcze dałoby się pewnie value uzyskać ale z wewnętrznego ? Właściwie jakbym wiedziała jak się do niego odwołać to może dalej by poszło. Żeby on jakie ID miał...

0

Terqaz dopiero weszłam na ten link ponownie, teraz to wygląda tak jak powinno, obadam to w wponiedziałek, teraz lecę :) Dzięki

0

Zrobiłem nieco bardziej złożony przykład, może to będzie bardziej klarowne: https://codesandbox.io/s/mom9jk3n7y .

0

Dzięki, poprzedni, to jest drugi sobotni był doskonały i jest zaadoptowany. Jest klarowny, a referencje to mało oczywista dla mnie sprawa. W ogóle React jest po byku po całości. Męczyłam się nad podpięciem stacjonarnego obrazka, potem okazało się że w oczywisty sposób to można podłączyć obrazek z sieci ale już nie ze swojego dysku. Jak na coś co w zasadzie nie zawiera nic ponad JS to trochę nie na moja wątrobę.
A tak w ogóle, w charakterze rewanżu - fajny przepis - zakładam, ze nie jesteś wege. Akurat na gotowaniu to się znam. Przyjmijmy że przepis kulinarny to też swojego rodzaju program :)

Weź łyżeczkę kminu rzymskiego, kurkumy, kolendry(nasiona), soli, zmiel w młynku do kawy.
Weź 3 połówki piersi kurczaka, potnij na kawałki - kęsy, wymieszaj z tym, co zmielone, odstaw na godzinę - dwie.
Weź dwa ząbki czosnku, kawałek imbiru(wielkości takiej, że po posiekaniu jest tego łyżka do zupy), NIEDZUŻY kawałek papryczki chilli posiekaj.
Weź trzy pomidory, wypestkuj - skórka wedle uznania, można zdjąć można zostawić, to mało ważne.
Weź jedną cebulę, pokrój.
Na dużą patelnię nalej oleju - 2-3 łyżki, jak zacznie dymić wrzuć kurczaka i cebulę, smaż mieszając przez 5 minut.

Dodaj imbir i czosnek, smaż 2 minuty
Dodaj pomidory, smaż przez 7 minut
Dodaj puszkę mleka kokosowego niesłodzonego (można dać trochę mniej - przy tej ilości jest to dość rzadkie ale mi takie pasi).
Zamieszaj, mleko powinno nabrać pomarańczowego koloru, jak już nie będzie go zmieniać na bardziej pomarańczowy gotowe.
Ewentualnie przed podaniem natka pietruszki albo ziele kolendry do posypania
Smacznego:)

0

No dzięki, też na gotowaniu się znam i coś podobnego w sumie kiedyś robiłem. Nie dodawałbym jedynie kolendry, no ale to kwestia gustu. ;)

1 użytkowników online, w tym zalogowanych: 0, gości: 1