Jika bidang teks yang memiliki fokus, dirender oleh setState
, itu kehilangan fokus.
+1
Saya harus menggunakan acara onBlur dengan defaultValue agar Textfields berfungsi dengan lancar.
ada yang punya solusi untuk membuat ini berfungsi?
Saya tidak berpikir ini menjadi masalah lagi. Lihat kode di bawah ini:
//taken from examples/webpack-example
/** In this file, we create a React component which incorporates components provided by material-ui */
const React = require('react');
const RaisedButton = require('material-ui/lib/raised-button');
const TextField = require('material-ui/lib/text-field');
const Dialog = require('material-ui/lib/dialog');
const ThemeManager = require('material-ui/lib/styles/theme-manager');
const LightRawTheme = require('material-ui/lib/styles/raw-themes/light-raw-theme');
const Colors = require('material-ui/lib/styles/colors');
const Main = React.createClass({
childContextTypes: {
muiTheme: React.PropTypes.object,
},
getInitialState () {
return {
muiTheme: ThemeManager.getMuiTheme(LightRawTheme),
counter: 0,
};
},
getChildContext() {
return {
muiTheme: this.state.muiTheme,
};
},
componentWillMount() {
let newMuiTheme = ThemeManager.modifyRawThemePalette(this.state.muiTheme, {
accent1Color: Colors.deepOrange500,
});
this.setState({muiTheme: newMuiTheme});
},
componentDidMount() {
this.refs.textField.focus();
},
render() {
console.log(this.state.counter);
let containerStyle = {
textAlign: 'center',
paddingTop: '200px',
};
let standardActions = [
{ text: 'Okay' },
];
return (
<div style={containerStyle}>
<Dialog
title="Super Secret Password"
actions={standardActions}
ref="superSecretPasswordDialog">
1-2-3-4-5
</Dialog>
<h1>material-ui</h1>
<h2>example project</h2>
<TextField ref="textField" onChange = {this._incrementStateCounter}/>
<RaisedButton label="Super Secret Password" primary={true} onTouchTap={this._handleTouchTap} />
</div>
);
},
_handleTouchTap() {
this.refs.superSecretPasswordDialog.show();
},
_incrementStateCounter () {
this.setState({counter: this.state.counter + 1});
},
});
module.exports = Main;
Inilah aplikasi yang sedang beraksi (dengan status yang diperbarui dicatat di konsol saat input TextField berubah). Anda dapat melihat bahwa BidangTeks mempertahankan fokus:
Saya masih mengerti. Contoh @ shaurya947 tidak mereproduksi bug karena BidangTeks tidak memiliki properti nilai awal.
untuk mereproduksi penggunaan
<TextField ref="textField" value={this.state.valueToBeEdited} onChange = {this._incrementStateCounter}/>
atau
<TextField ref="textField" defaultValue={this.state.valueToBeEdited} onChange = {this._incrementStateCounter}/>
Saya juga melihat apa yang tampaknya merupakan kemunduran dari masalah ini. TextFields saya kehilangan fokus pada render ulang. Saya menyetel value
prop dari TextField
, jadi ini adalah komponen terkontrol.
Saya melihat peringatan baru di konsol: 'TextField mengubah input teks jenis yang tidak terkontrol untuk dikontrol'. Saya tidak ingat pernah melihatnya sebelumnya, tidak yakin apakah itu relevan di sini atau tidak. Peringatan muncul setelah saya memasukkan karakter pertama ke dalam TextField
.
Melalui sedikit debugging, tampaknya ada sesuatu yang menyebabkan TextField
kehilangan fokus. Internal onBlur
handler dipanggil, yang matikan isFocused
keadaan internal dari TextField
false. Jika saya mencatat document.activeElement
selama handler onBlur
(untuk menentukan komponen apa yang mencuri fokus) maka ia mencatat root dokumen (body).
Saya dapat mempersempitnya lebih jauh dengan menentukan bahwa sumber peristiwa blur adalah MenuItem
dalam Menu
di tempat lain dalam aplikasi. Menyetel properti disableAutoFocus
menjadi true
menyelesaikan masalah saya. Semoga ini bisa membantu orang lain.
Saya telah membuka terbitan terpisah untuk menangkap ini: # 4387.
Saya dapat mengonfirmasi bahwa ini masih menjadi masalah ...
Melihatnya dalam bentuk login yang sangat sederhana - Saya menggunakan ini sehubungan dengan formulir redux dan ketika saya berinteraksi dengan formulir itu menyebabkan render ulang (menyentuh bidang dalam bahasa bentuk redux) yang kehilangan fokus.
Sebagai solusinya, saya hanya merender ulang bentuk sebenarnya jika ada perubahan dalam status kesalahan.
Anda dapat mereproduksi masalah ini dengan mudah dengan meletakkan TextField
dalam Table
ditetapkan sebagai selectable=true
. Setiap kali Anda mengklik bidang teks untuk mulai mengeditnya, garis akan mendapatkan fokus, sehingga mengubah warna latar belakangnya (saya kira beberapa props
baris mungkin ditetapkan sebagai selected=true
), jadi memicu render ulang, sehingga Anda akan kehilangan fokus ...
Jadi pada dasarnya Anda tidak dapat menggunakan TextField
dalam selectable
Table
, tidak yakin ini adalah praktik UX yang baik, tapi tetap saja :)
Kami memperhatikan bahwa pada proyek kami, saya dapat mencoba mendorong reproduksi.
Ada solusi untuk ini? Juga memperhatikan ini saat menggunakan area teks input biasa di dalam tabel.
@ dalexander01 Menemukan "solusi", tetapi tampaknya sangat spesifik bentuk redux karena mengalami masalah yang sama ketika tidak menggunakan komponen masukan md. Jika ada gunanya saya dapat memposting potongan!
@deyceg tolong lakukan, tidak ada salahnya 😄. Baru saja mengalami masalah ini dengan kombinasi <Dialog/>
dan <TextField/>
.
<Dialog
open={this.props.showDialog}
title={'New ' + this.props.type}
autoScrollBodyContent={true}
actions={actions}
bodyStyle={styles.dialogContent}
>
<SelectField
name='sub_type'
value={this.props.top_card.sub_type}
onChange={(e, k, payload) => this.props.topCardSelectChange('sub_type', payload)}
floatingLabelText='Type'
>
{menuItemsJSX}
</SelectField>
<TextField
name='title'
className='story-title'
value={this.props.top_card.title}
onChange={this.props.topCardChange}
floatingLabelText='Title'
fullWidth={true}
multiLine={true}
style={styles.title}
/>
<TextField />
</Dialog>
Saya menyelesaikannya untuk kasus saya, Anda perlu memberikan id unik ke bidang teks itu.
Id tidak boleh berubah setelah dirender ulang. Dengan cara ini, React dapat melacak elemen mana yang difokuskan atau tidak.
PS Saya memiliki textfields dalam array yang diberikan melalui myArray.map, di sana Anda harus memberikan kunci yang sama saat membuat ulang.
EDIT: Saya menguji lagi, hanya memiliki "kunci" di myArray agar sama di seluruh render yang memecahkan masalah.
Id textfield diubah menjadi shortid.generate ().
params.map(function(p,i){
return(
<div key={i}> <--- this will always be the same for this particular row.
<div className='param-inner'>
<TextField id={shortid.generate()} value = {p.value} onChange={this.updateParam.bind(this,i)}/> <-- id here can be random, but it is necessary to avoid browser warning "we don't have enough information..."
</div>
<div className='param-inner'>{p.unit}</div>
</div>
)
}.bind(this));
Adakah yang berhasil menemukan solusi untuk masalah ini (tanpa menggunakan refs
)? Tampaknya kombinasi dari onChange
dan pengaturan value
prop ke tombol status yang membuat input menjadi tidak fokus.
Saya memiliki masalah berikut juga, saya menyelesaikannya meskipun dengan mengambil implementasi SelectField jika Anda melihatnya secara internal memanggil DropdownMenu https://github.com/callemall/material-ui/blob/ccf712c5733508784cd709c18c29059542d6aad1/src/SelectField/SelectField. js # L192
jadi saya juga membutuhkannya untuk menambahkan DropDownMenu ini secara internal membungkus komponen dalam Menu, saya menambahkan disableAutoFocus untuk membuat TextField saya tetap fokus padanya seperti yang ditunjukkan di bawah.
Mungkin kita bisa mengekspos komponen DropDownMenu dari SelectField dan mengizinkan autofokus dinonaktifkan dengan props.
Salah satu solusi untuk ini bagi mereka yang berjuang dengan itu dan hanya ingin sesuatu bekerja, meskipun kemungkinan itu mungkin tidak berlaku dalam beberapa situasi dan dapat menimbulkan masalah (saya sendiri tidak sepenuhnya yakin) adalah dengan menggunakan variabel pada contoh sebagai gantinya daripada negara bagian. Jadi daripada this.state.value
itu akan menjadi this.value
bahwa onChange
akan diperbarui. Komponen tidak akan memiliki value
prop. Kemudian pada handler onChange
Anda akan menggunakan e.target.value
.
Satu-satunya perbedaan yang saya ketahui antara variabel pada instance vs. status adalah bahwa instance var tidak akan memicu render ulang. Meskipun mungkin ada alasan lain jadi saya berharap orang lain akan menangkap kelonggaran saya dalam hal ini.
Masih mendapatkan kesalahan ini. Ada solusi?
Solusi yang saya temukan adalah mengganti fungsi shouldComponentUpdate ke komponen saya dan kemudian mengembalikan false ketika saya mengubah nilai status yang digunakan oleh bidang teks saya.
`shouldComponentUpdate(nextProps, nextState) {
if(nextState.email != this.state.email) {
return false;
}
else if(nextState.password != this.state.password) {
return false;
}
else return true;
}
`
Melakukannya dengan cara ini memperbaiki masalah saya. Masalahnya tampaknya menjadi rendering komponen setiap kali status berubah yang kemudian menyetel ulang fokus. Jadi dengan menggunakan fungsi di atas untuk menonaktifkan rendering ketika Anda melakukan acara onChange untuk menyetel nilai status, komponen tidak dimuat ulang.
@ Aspintyl000 ini bekerja ... agak. Ketika saya menyetel nilai bidang teks melalui prop 'nilai', dan saya menyetel prop itu ke 'this.state.value', tidak ada yang muncul. Meskipun, ketika saya menghapusnya, sepertinya berhasil.
saya menggunakan textfields dalam baris tabel, dan ini adalah masalah :( ada kemajuan?
Saya juga mendapatkan kesalahan yang sama. Tetapi setelah menggunakan componentDidMount () {
this.refs.textField.focus ();
}
itu tidak kehilangan fokus. Tetapi itu tidak menunjukkan nilai masukan.
Saya mencoba menambahkan <TextField />
dalam <Table />
. Seperti situasi di atas, saya tidak dapat memfokuskan masukan.
Solusi saya: tambahkan acara onClick
keselectable=false
. Setelah operasi masukan Anda, gunakan peristiwa onBlue
untuk menyetel tabel selectable=true
.
Perilaku yang sangat menjengkelkan.
Saya mengalami ini setelah membungkus dua kotak masukan dengan komponen bergaya. Div luar benar-benar merusak perilakunya. Ini adalah cacat yang mengerikan dalam desain perpustakaan ini.
Jadi ini adalah solusi yang cukup buruk tetapi yang berikut berfungsi, sebagian besar:
`` ''
onSomeValueChanged = event => {
this.props.someValueChanged (event.target.value);
const { target } = event;
setTimeout(() => {
target.focus();
}, 10);
};
`` ''
Ya, tidak cantik ...
@scotmatson "Perilaku yang sangat menjengkelkan ... cacat yang mengerikan dalam desain perpustakaan ini". Ini adalah perangkat lunak gratis, dibuat oleh sukarelawan ... meskipun demikian, hasil yang bagus tentang hubungan dengan styled-components
.
@scotmatson Saya dapat mengonfirmasi bahwa, setidaknya dalam kasus saya, masalah terselesaikan jika saya mengubah Container = styled.div
yang saya miliki sebagai pembungkus menjadi normal, komponen non-gaya div
.
Edit:
Dan saya juga berbagi rasa frustrasi Anda. Akan sangat menyenangkan jika kedua perpustakaan ini bekerja bersama dengan sempurna. Masalah ini dan masalah kekhususan adalah dua hal yang saya harap bisa segera diselesaikan tetapi saya berterima kasih atas orang-orang yang meluangkan waktu mereka.
Edit2:
Saya baru saja menemukan apa yang menyebabkan masalah dalam kasus saya: mendeklarasikan komponen komponen bergaya dalam metode render! Hal ini menyebabkan komponen dibuat ulang pada setiap render ulang dan React tidak dapat melacak elemen mana yang memiliki fokus melintasi batas render ulang. Ini juga menyebabkan beberapa masalah render ulang lainnya bagi saya.
Memindahkan semua deklarasi komponen bergaya saya ke luar komponen menyelesaikan masalah kehilangan fokus bagi saya. Mungkin kesalahan noob tetapi tidak ada yang menyebutkan itu di sini jadi saya pikir saya akan kembali dan melaporkan.
Masalah yang tampaknya saya hadapi adalah bahwa fokusnya banyak setiap kali TextFields (atau Input) sedang dirender di dalam object.map (). BidangTeks di luar peta berfungsi dengan sempurna. Apakah saya kehilangan alat peraga atau apa pun? Saya benar-benar tersesat
Saya mencoba hampir setiap solusi yang disarankan di utas ini tanpa hasil.
Struktur kasarnya begini
File Utama
...
function Steps(props) {
const { steps } = props;
if(steps) {
return steps.map((step, index) => (
<div key={(step.order === '' ? index : step.order)}>
<NewUxCard step={step} index={index} onChange={props.onChange}
onChangeCard={props.onChangeCard} onParamChange={props.onParamChange}/>
</div>
));
}
}
<div>
<TextField/> //working
<Steps steps={this.props.ux.steps} onChange={this.onChange}
onChangeCard={this.handleChangeCard} onParamChange={this.handleParamChange} />
</div>
NewUxCard
...
<div>
<TextField type="text" fullWidth id={"qq"+this.props.index} label="Name"
value={this.props.step.name} onChange={this.props.onChangeCard('name', this.props.index)} margin="normal" /> //not working - loses focus on each key stroke
</div>
Perlu dicatat bahwa saya menggunakan Redux-React, jadi perubahan status melewati input-> action-> reducer
Ada ide? Terima kasih
EDIT 1:
Penyelidikan lebih lanjut tentang masalah ini, saya telah mempersempitnya dan menyelesaikannya dengan menghapus fungsi reaksi Langkah (alat peraga) yang digunakan untuk membuat Tag
Jadi sebelumnya, strukturnya dulu
@piltsen Saya baru saja mengalami masalah ini di v1.5.0 saat merender TextFields di .map()
- Saya mempersempitnya ke kunci TextField saya menjadi nilai yang sama dengan input, jadi ketika diubah kemungkinan menyebabkan TextField dipasang lagi dan kehilangan fokus. Tidak yakin apakah itu membantu Anda - meskipun saya yakin sekarang Anda telah memilahnya
Ini juga merupakan gejala menggunakan alat peraga render. Melakukan sesuatu seperti
<HigherOrderComponent
render={hocProps => <TextField value={...} onChange={...} />
/>
dapat menyebabkan perilaku ini. Untuk memperbaikinya, teruskan fragmen jika diizinkan oleh desain:
<HigherOrderComponentThatDoesntPassOwnState
component={<TextField {...this.props}/>}
/>
Dalam kasus saya sepertinya tidak fokus hilang tetapi kursor menghilang dari TextField. Saya dapat memeriksa document.activeElement sama dengan TextField saya, saya dapat menggunakan perintah keyboard dan roda mouse untuk mengubah nilai (nomor jenis), tetapi setiap jenis peredam yang dijalankan terjadi dan kursor hilang.
Kemudian di atas render saya mencari berdasarkan id TextField saya dan membuat
MyTextField.blur();
MyTextField.focus();
, yang tidak membantu. Tetapi ketika saya membuat fokus () dengan beberapa waktu tunggu , sepertinya berhasil.
Edit:
Nah, di dalam HOC masih belum berfungsi, jadi sepertinya perlu mendorongnya juga.
@ younes0 Saya dapat mengonfirmasi bahwa perbaikannya juga untuk saya. Dalam kasus saya, saya memiliki komponen stateless helper yang akan mengembalikan TextField dengan beberapa set props umum dan kemudian menyebarkan props lainnya ke dalamnya, jadi saya tidak perlu menentukan hal-hal seperti className
atau variant
beberapa kali di seluruh formulir. Bidang teks saya kehilangan fokus segera setelah ada perubahan apa pun pada formulir, dan menghapus fungsi pembantu dan hanya membuat mentah TextField
s berulang kali memperbaikinya.
Bisakah ini dibuka kembali, atau haruskah masalah baru diajukan?
Saya masih mendapatkan masalah ini, saya menggunakan 3.2.0
@OmarDavilaP Bisakah Anda membuat edisi baru dengan reproduksi?
Saya menyelesaikannya untuk kasus saya, Anda perlu memberikan id unik ke bidang teks itu.
...
Id tidak boleh berubah setelah dirender ulang. Dengan cara ini, React dapat melacak elemen mana yang difokuskan atau tidak.
PS Saya memiliki textfields dalam array yang diberikan melalui myArray.map, di sana Anda harus memberikan kunci yang sama saat membuat ulang.EDIT: Saya menguji lagi, hanya memiliki "kunci" di myArray agar sama di seluruh render yang memecahkan masalah.
Id textfield diubah menjadi shortid.generate ().params.map(function(p,i){ return( <div key={i}> <--- this will always be the same for this particular row. <div className='param-inner'> <TextField id={shortid.generate()} value = {p.value} onChange={this.updateParam.bind(this,i)}/> <-- id here can be random, but it is necessary to avoid browser warning "we don't have enough information..." </div> <div className='param-inner'>{p.unit}</div> </div> ) }.bind(this));
Yup, ini menyelesaikan masalah dalam kasus saya, pada dasarnya saya menggunakan:
<NewTextField key={user.id+Math.random()}>
Saya menggantinya dengan:
<NewTextField key={user.id}>
Jadi, ya tampaknya praktik yang buruk menghasilkan kunci acak setiap kali merender ulang komponen.
Bagi saya masalahnya adalah, saya membuat fungsi pembungkus untuk TextField, namun saya menyatakan fungsi itu di dalam fungsi komponen saya, setelah dipindahkan ke luar fungsi saya semuanya bekerja seperti yang diharapkan!
Saya membuat contoh kotak kirim https://codesandbox.io/s/material-demo-msbxl?fontsize=14&hidenavigation=1&theme=dark
Saya mengalami masalah ini dengan rendering bersyarat. Saya memiliki objek javascript dalam render yang mengembalikan berbagai komponen dalam file .js. Maaf, saya tidak menjelaskannya dengan benar. Ketika saya memperbaikinya, saya akan mengedit posting ini, jika saya ingat.
edit: Yay, saya memperbaikinya! Saya percaya cara saya merender secara bersyarat adalah merender setiap komponen bahkan ketika tidak ditampilkan. Saya memindahkan logika di luar render dan tampaknya berfungsi dengan baik sekarang. Ini kode lama:
edit: saya tidak bisa menjadi gaya pada hal ini jadi tidak apa-apa.
Saya mengalami masalah ini hari ini dan kepala saya terbentur selama beberapa jam. Dalam kasus saya, apa yang saya lakukan salah adalah membungkus TextField
dalam komponen stateless untuk mengatur halaman saya dengan lebih baik (jangan membuat beberapa jika data sedang dimuat, dll dll), tetapi saya meninggalkan useState
callback yang mengontrol TextField
dalam komponen induk.
Untuk anak cucu, berikut ini tautan kode dan kotak kecil untuk mereproduksi kebodohan saya: https://codesandbox.io/s/mui-textedit-losefocus-g6xxb
Pertanyaannya sekarang adalah, bagaimana saya membuat komponen kustom saya yang membungkus TextField
? Baik HOC maupun createElement
tampaknya mengalami bug ini:
const MyField= ({ name, ...props }) => (
<TextField
fullWidth
variant="outlined"
size="small"
name={name}
{...props}
/>
);
const MyField= ({ name, ...rest }) => {
return React.createElement(TextField, {
fullWidth: true,
variant: "outlined",
size: "small",
name: name,
{...rest}
});
};
Tidak masalah, pendekatan di atas berfungsi dengan baik - saya menyadari bahwa saya telah menentukan komponen kustom di dalam komponen induk, yang menyebabkan masalah. Ketika dipindahkan ke luar lingkup induk (seperti seharusnya) itu berfungsi dengan baik - Saya memperbarui kotak pasir sebelumnya untuk menunjukkan pendekatan yang benar: https://codesandbox.io/s/mui-textedit-losefocus-g6xxb
Bagi saya masalahnya adalah, saya membuat fungsi pembungkus untuk TextField, namun saya menyatakan fungsi itu di dalam fungsi komponen saya, setelah dipindahkan ke luar fungsi saya semuanya bekerja seperti yang diharapkan!
Saya membuat contoh kotak kirim https://codesandbox.io/s/material-demo-msbxl?fontsize=14&hidenavigation=1&theme=dark
Ini adalah masalahku. Terima kasih!
Tidak masalah, pendekatan di atas berfungsi dengan baik - saya menyadari bahwa saya telah menentukan komponen kustom di dalam komponen induk, yang menyebabkan masalah. Ketika dipindahkan ke luar lingkup induk (seperti seharusnya) itu berfungsi dengan baik - Saya memperbarui kotak pasir sebelumnya untuk menunjukkan pendekatan yang benar: https://codesandbox.io/s/mui-textedit-losefocus-g6xxb
Terima kasih. Ini berhasil!
Bagi saya masalahnya adalah, saya membuat fungsi pembungkus untuk TextField, namun saya menyatakan fungsi itu di dalam fungsi komponen saya, setelah dipindahkan ke luar fungsi saya semuanya bekerja seperti yang diharapkan!
Saya membuat contoh kotak kirim https://codesandbox.io/s/material-demo-msbxl?fontsize=14&hidenavigation=1&theme=dark
@ fleischman718 terima kasih telah mencari tahu yang ini! Menghapus fungsi komponen pembungkus untuk BidangTeks di dalam definisi komponen induk memperbaiki masalah saya!
Butuh beberapa saat bagi saya untuk mencari tahu apa yang terjadi di kotak pasir, jadi saya membuat ringkasan di bawah ini:
import { TextField } from '@material-ui/core';
const ParentComponent = () => {
// DON'T DO THIS!!!
// fix issue by moving this component definition outside of the ParentComponent
// or assign the TextField to a variable instead
const TextFieldWrapper = () => (
<TextField />
);
return (
<div>
<TextFieldWrapper />
</div>
)
}
Komentar yang paling membantu
@scotmatson Saya dapat mengonfirmasi bahwa, setidaknya dalam kasus saya, masalah terselesaikan jika saya mengubah
Container = styled.div
yang saya miliki sebagai pembungkus menjadi normal, komponen non-gayadiv
.Edit:
Dan saya juga berbagi rasa frustrasi Anda. Akan sangat menyenangkan jika kedua perpustakaan ini bekerja bersama dengan sempurna. Masalah ini dan masalah kekhususan adalah dua hal yang saya harap bisa segera diselesaikan tetapi saya berterima kasih atas orang-orang yang meluangkan waktu mereka.
Edit2:
Saya baru saja menemukan apa yang menyebabkan masalah dalam kasus saya: mendeklarasikan komponen komponen bergaya dalam metode render! Hal ini menyebabkan komponen dibuat ulang pada setiap render ulang dan React tidak dapat melacak elemen mana yang memiliki fokus melintasi batas render ulang. Ini juga menyebabkan beberapa masalah render ulang lainnya bagi saya.
Memindahkan semua deklarasi komponen bergaya saya ke luar komponen menyelesaikan masalah kehilangan fokus bagi saya. Mungkin kesalahan noob tetapi tidak ada yang menyebutkan itu di sini jadi saya pikir saya akan kembali dan melaporkan.