2017-07-23 2 views
0

Je veux une liste d'entrées de texte qui sont en synchronisation avec une liste de valeurs que j'ai dans le backend. Donc, en tapant dans les mises à jour les valeurs, et les mises à jour des valeurs reflètent dans les entrées de texte.React - Entrée de texte de liaison bidirectionnelle avec un format différent entre stocké et affiché

Ceci est une situation de liaison 2 voies typique avec quelque chose comme ceci:

class BoundInput extends Component { 

    constructor(props) { 
     super(props); 
     this.state = {textVal: ''}; 
    } 

    handleChange = evt => this.setState({textVal: evt.target.value}); 

    render() { 
     return <input type="text" 
         value={this.state.textVal} 
         onChange={this.handleChange} /> 
    } 

} 

Mais je voudrais stocker la valeur pas exactement ce que l'utilisateur a tapé, mais, par exemple, une conversion de cm.

Malheureusement, la conversion et la conversion ne sont pas parfaites.

E.g. taper '2.' est immédiatement converti en '2', de sorte que vous êtes coincé si vous voulez taper une décimale et tout ce qui va au-delà.

Je voudrais être en mesure d'avoir la valeur stockée à jour l'affichage d'entrée à moins l'entrée est active, auquel cas il ne doit être mise à jour de la valeur stockée de l'entrée.

J'ai donc une valeur booléenne qui me permet de passer sous condition à value à l'entrée de texte, de sorte que le typer peut entrer sans entrave, et l'affichage peut mettre à jour une représentation équivalente une seule fois qu'ils quittent mise au point (par exemple '1.' devient soudainement '1' ou '1.0'), ce qui est bien.

J'ai essayé cela mais j'ai l'erreur qu'un composant d'entrée doit être contrôlé, ou non, pendant toute sa durée de vie. Pas de changement comme je l'ai fait.

Des suggestions sur la stratégie globale, ou contourner cet avertissement particulier sur contrôlé vs non contrôlé?

Peut-être un moyen de tuer et de re-monter le composant d'entrée avant de passer de passer value à ne pas passer value?

Quelque chose que j'ai fait qui est laid comme tout diable est juste de dupliquer mon composant d'entrée (que j'appelle NiceInput), et quand il n'est pas actif, je permute le duplicata NiceInput2. Cela fonctionne, mais il doit y avoir un moyen moins ridicule que de dupliquer des composants: D

Répondre

1

Vous pouvez stocker une 2ème variable dans l'état où vous faites constamment "makeNice" la valeur du texte, et désélectionnez, affecter la bonne valeur à la valeur de texte visible.

Vous utilisez toujours le « onDeselect », mais vous enregistrez faire une 2ème composante

class BoundInput extends Component { 

    constructor(props) { 
     super(props); 
     this.state = {textVal: '', niceVal: ''}; 
    } 

    handleChange = evt => { 
     this.setState({ 
      textVal: evt.target.value, 
      niceVal: makeNice(evt.target.value), 
     });  
    } 

    handleDeselect =() => {this.setState({textVal: this.state.niceVal});} 

    render() { 
     return <input type="text" 
         value={this.state.textVal} 
         onChange={this.handleChange} 
         onDeselect={this.handleDeselect} 
       /> 
    } 

} 
0

Ce que je fini par faire est la création d'un composant UncontrolledInput qui supprime la value de accessoires avant de transmettre le reste des accessoires pour le input.

const UncontrolledInput = ({ value, ...otherProps }) => { 
    return (
    <input {...otherProps} /> 
) 
} 

et je rendais un UncontrolledComponent au lieu de mon composant d'entrée normale lorsque l'utilisateur a été taper dedans. Donc, la valeur stockée était mise à jour par leur frappe, mais pendant qu'ils tapaient, rien n'écrivait la valeur de cet élément d'entrée en plus des frappes de l'utilisateur.

Mais ma version finale était la suivante:

const UncontrolledInput = ({ value, focusOnMount, ...otherProps }) => { 
    otherProps.defaultValue = value; 
    if (focusOnMount) { 
    otherProps.ref = input => input && input.focus(); 
    } 
    return (
    <input {...otherProps} /> 
) 
} 

Les 2 ajouts importants:

1) au moins à partir la valeur de l'entrée avec ce que le parent a essayé de passer dans

2) une option pour focaliser l'entrée une fois qu'elle est montée (puisque le remplacement d'une entrée avec cet équivalent non contrôlé est susceptible de se produire lorsque vous voulez que l'entrée soit focalisée, mais ce remplacement de composant le rend non initia initia lly)

I atteint ces domaines:

1) defaultValue

2) refsee this question/answer about focusing on mount