web-dev-qa-db-fra.com

Dans React ES6, pourquoi le champ de saisie perd-il le focus après la saisie d'un caractère?

Dans mon composant ci-dessous, le champ de saisie perd le focus après la saisie d'un caractère. Lors de l'utilisation de l'inspecteur de Chrome, il semble que le formulaire entier soit rendu de nouveau au lieu de l'attribut value du champ de saisie lors de la saisie.

Je ne reçois aucune erreur ni eslint ni Chrome Inspector.

Soumettre le formulaire lui-même fonctionne de la même manière que le champ de saisie lorsqu'il est situé dans le retour du rendu ou lorsqu'il est importé en tant que composant distinct, mais pas dans la manière dont il est codé ci-dessous.

Pourquoi cela est-il ainsi?

Composant de la page principale

import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import * as actionPost from '../redux/action/actionPost';
import InputText from './form/InputText';
import InputSubmit from './form/InputSubmit';

class _PostSingle extends Component {
    constructor(props, context) {
        super(props, context);
        this.state = {
            post: {
                title: '',
            },
        };
        this.onChange = this.onChange.bind(this);
        this.onSubmit = this.onSubmit.bind(this);
    }
    onChange(event) {
        this.setState({
            post: {
                title: event.target.value,
            },
        });
    }
    onSubmit(event) {
        event.preventDefault();
        this.props.actions.postCreate(this.state.post);
        this.setState({
            post: {
                title: '',
            },
        });
    }
    render() {
        const onChange = this.onChange;
        const onSubmit = this.onSubmit;
        const valueTitle = this.state.post.title;
        const FormPostSingle = () => (
            <form onSubmit={onSubmit}>
                <InputText name="title" label="Title" placeholder="Enter a title" onChange={onChange} value={valueTitle} />
                <InputSubmit name="Save" />
            </form>
        );
        return (
            <main id="main" role="main">
                <div className="container-fluid">
                    <FormPostSingle />
                </div>
            </main>
        );
    }
}

_PostSingle.propTypes = {
    actions: PropTypes.objectOf(PropTypes.func).isRequired,
};

function mapStateToProps(state) {
    return {
        posts: state.posts,
    };
}

function mapDispatchToProps(dispatch) {
    return {
        actions: bindActionCreators(actionPost, dispatch),
    };
}

export default connect(mapStateToProps, mapDispatchToProps)(_PostSingle);

Composant de saisie de texte

import React, { PropTypes } from 'react';

const InputText = ({ name, label, placeholder, onChange, value, error }) => {
    const fieldClass = 'form-control input-lg';
    let wrapperClass = 'form-group';
    if (error && error.length > 0) {
        wrapperClass += ' has-error';
    }
    return (
        <div className={wrapperClass}>
            <label htmlFor={name} className="sr-only">{label}</label>
            <input type="text" id={name} name={name} placeholder={placeholder} onChange={onChange} value={value} className={fieldClass} />
            {error &&
                <div className="alert alert-danger">{error}</div>
            }
        </div>
    );
};

InputText.propTypes = {
    name: PropTypes.string.isRequired,
    label: PropTypes.string.isRequired,
    placeholder: PropTypes.string.isRequired,
    onChange: PropTypes.func.isRequired,
    value: PropTypes.string,
    error: PropTypes.string,
};

InputText.defaultProps = {
    value: null,
    error: null,
};

export default InputText;

Composant du bouton d'envoi

import React, { PropTypes } from 'react';

const InputSubmit = ({ name }) => {
    const fieldClass = 'btn btn-primary btn-lg';
    return (
        <input type="submit" value={name} className={fieldClass} />
    );
};

InputSubmit.propTypes = {
    name: PropTypes.string,
};

InputSubmit.defaultProps = {
    name: 'Submit',
};

export default InputSubmit;
8
spunge

Qu'est-ce qui se passe est la suivante:

Lorsque votre événement onChange est déclenché, le rappel appelle setState avec la nouvelle valeur de titre, qui est transmise à votre champ de texte en tant que prop. À ce stade, React le restitue de nouveau, raison pour laquelle vous perdez la concentration.

Ma première suggestion serait de fournir les clés de vos composants, en particulier le formulaire et l’entrée elle-même. Les clés permettent à React de conserver l’identité des composants lors des rendus.

6
Ezra Chang

c'est parce que vous rendez le formulaire dans une fonction dans render ().

Chaque fois que votre état/accessoire change, la fonction renvoie un nouveau formulaire. cela vous a fait perdre le focus.

Essayez de placer directement le contenu de la fonction dans votre rendu.

       <main id="main" role="main">
            <div className="container-fluid">
                <FormPostSingle />
            </div>
        </main>

====>

       <main id="main" role="main">
            <div className="container-fluid">
                <form onSubmit={onSubmit}>
                    <InputText name="title" label="Title" placeholder="Enter a title" onChange={onChange} value={valueTitle} />
                    <InputSubmit name="Save" />
                </form>
            </div>
        </main>
0
Alex Yan

Je ne suis pas autorisé à commenter alors ce doit être une réponse. J'ai eu le même problème et la réponse d'Alex Yan était correcte.

A savoir j'avais cette fonction 

const DisplaySearchArea =()=>{return (arrayOfSearchFieldNames.map((element, index)=>{return(<div key ={index} className = {inputFieldStyle}><input  placeholder= {arrayOfPlaceholders[index]} type="text" className='border-0'
value={this.state[element]}
onChange={e => {this.setState({ [element]: e.target.value }); console.log(e.target)}}
onMouseEnter={e=>e.target.focus()}/></div>)}))}

cela se comporte bien avec FF et non avec Chrome lorsqu'il est rendu en tant que <DisplaySearchArea /> Lorsque rendu en tant que {...} c'est correct avec les deux. Ce n'est pas un code à la fois «beau» mais qui marche, on m'a déjà dit d'avoir tendance à abuser des lambdas.

0
Kiszuriwalilibori

Mon problème était qu'il restituait un composant sans état dans le même fichier. Donc, une fois que je me suis débarrassé de ce composant sans état et que je viens de mettre le code directement, je n'ai pas eu de re-rendus inutiles

render(){
   const NewSocialPost = () => 
       <div className='new-post'>
           <input
                onChange={(e) => this.setState({ newSocialPost: e.target.value })}
                value={this.state.newSocialPost}/>
           <button onClick={() => this._handleNewSocialPost()}>Submit</button>
      </div>

return (
            <div id='social-post-page'>
                <div className='post-column'>
                    <div className='posts'>
                        <Stuff />
                    </div>
                    <NewSocialPost />
                </div>
                <MoreStuff />
            </div>
0
Kevin Danikowski