Реагировать: Доступ к свойствам динамически созданных элементов по ссылкам - PullRequest
1 голос
/ 13 мая 2019

У меня есть динамически созданный список из 5 элементов ввода.Теперь, когда я щелкаю значок элемента «плюс» (из IonicIcons) в React, я хочу, чтобы первое из этих полей ввода было сфокусировано.

Мой список ввода:

if (actualState.showInputField === true) {
            inputField = (
            <div>       
                {                    
                    actualState.inputFields.map((val,index) => (   
                        <ListElemErrorBoundary key={index}>                   
                            <InputElement key={index} elemValue = {val} name={"input" +  index} onChangeListener={(event) => handleDoublettenIDs(event,index)} />
                        </ListElemErrorBoundary>  
                        )
                    )
                }                
                {actualState.errorMessage!= '' ? <Alert color="danger" >{actualState.errorMessage}</Alert> : null}
                {actualState.successMessage !='' ? <Alert color="success" >{actualState.successMessage}</Alert> : null} 
                <br />                    
                <p><button onClick = { () =>  {
                    handleInputs(props.anzeigeID);    
                    vanishMessage();                
                    }                
                }>absenden</button></p>   
            </div>  
            )
        }
        return inputField;
    }

МойЗначок:

const checkIcon = () => {
        let showIcon = null;
        if (actualState.showInputField === false) {
            showIcon = (
               <IoIosAddCircleOutline ref={toggleSignRef} onClick = {toggleInput}
                />
            )
        } else {
            showIcon = (
                <IoIosRemoveCircleOutline onClick = {toggleInput}
                />
            )
        }
        return showIcon;
    }

Я, вероятно, должен поместить свой ref в элементы списка, однако, я думаю, что для каждого нового элемента списка этот ref "перезаписывается", потому что у меня есть только один ref.Должен ли я сделать что-то вроде запроса ключа ввода, чтобы выяснить, какой это элемент ввода ключа списка, и если это первый индекс ключа ввода, я выполню фокус на этом элементе ввода?

И как тогда можноЯ получаю первый элемент ввода внутри метода toggleInput (), где я устанавливаю значение showInputField?Можно ли как-то запросить props.key ссылки на этот элемент ввода?

Этот компонент является функциональным компонентом, и я использую только useRef ...

Мой компонент:

import React, {useState, useRef, useEffect} from "react";
import { IoIosAddCircleOutline } from 'react-icons/io';
import { IoIosRemoveCircleOutline } from 'react-icons/io';
import InputElement from './inputElementDublette';
import fetch from 'isomorphic-unfetch';
import getConfig from 'next/config';
import ListElemErrorBoundary from './ListElemErrorBoundary';
import { Button, Alert  } from 'reactstrap';

let url_link;
let port = 7766; 

const { serverRuntimeConfig, publicRuntimeConfig } = getConfig();
const apiUrl = publicRuntimeConfig.apiUrl; //|| publicRuntimeConfig.apiUrl;
const server = publicRuntimeConfig.SERVERNAME;

let doublettenListe_link = `http://${server}:${port}/doubletten/`;


//functional component with state, with useState
const DubletteComponent = props => {
    const toggleSignRef = useRef();

    const [actualState, changeState] = useState({
        showInputField: false,
        dublettenIDs: [],
        errorMessage: '', 
        successMessage: '',  
        inputFields: ['','','','',''],                
        visible : false,
    });    


    const toggleInput = () => {
        changeState({...actualState, showInputField: !actualState.showInputField});
    }

    const vanishMessage = ()=>{    
          window.setTimeout(() => {
            changeState({
                ...actualState,
                errorMessage:'',
                successMessage: '',        
            });
          },7000);
      }


    const handleDoublettenIDs = (event,index) => { 
        let idnumber = event.target.value;
        let newInputFields = [...actualState.inputFields];
        newInputFields.splice(index,1, idnumber);
        //console.log("new:",newInputFields);
        if (isNaN(idnumber)) {
            changeState({...actualState, errorMessage: 'ID is not a number'})
        } if (idnumber > 2147483647) {
            changeState({...actualState, errorMessage: 'Number can not be bigger than 2147483647!'})
        }        
        else {
            changeState({...actualState, inputFields: newInputFields, errorMessage: '' });
        }      
    }

    const handleInputs = (anzeigeID) => {
        if (process.browser && apiUrl==='dev') {
            doublettenListe_link = `http://localhost:${port}/doubletten/`;
        }
        if (actualState.errorMessage=='') {
            let array = actualState.inputFields;
            let filtered = array.filter(function(el) {
                return el != '';
            });                                   
            const requestOptions = {
                method: 'POST',
                headers: {'Accept': 'application/json', 'Content-Type':'application/json'},            
                body: JSON.stringify({
                    id: anzeigeID,
                    dublettenIDs: filtered
                })
            };
                //console.log("inputfields:",filtered);
              // Note: I'm using arrow functions inside the `.fetch()` method.
              // This makes it so you don't have to bind component functions like `setState`
              // to the component.
              //console.log("link:", doublettenListe_link);
            fetch(doublettenListe_link , requestOptions)
            .then((response) => { 
                //console.log("Resp:", response);
                let tempArray = ['','','','',''];
                changeState({...actualState, inputFields: tempArray});   
                //console.log(actualState);        
                changeState({...actualState, dublettenIDs: []});  
                changeState({...actualState, successMessage: `Doubletten-IDs wurden erfolgreich eingetragen!`});

                return response;          
            }).catch((error) => {
                changeState({...actualState, errorMessage: `Error beim Eintrage der Dubletten. Bitte prüfen, ob der Server läuft. Error: ${error.statusText}`});
            });  
        }       
    }

    const checkIcon = () => {
        let showIcon = null;
        if (actualState.showInputField === false) {
            showIcon = (
               <IoIosAddCircleOutline onClick = {toggleInput}
                />
            )
        } else {
            showIcon = (
                <IoIosRemoveCircleOutline onClick = {toggleInput}
                />
            )
        }
        return showIcon;
    }

    const checkPrerequisites = () => {
        //let errorMessage = '';
        let inputField = null;
        // if (actualState.errorMessage != '') {
        //     errorMessage = (
        //         <Alert color="danger">{actualState.errorMessage}</Alert>
        //     )
        // }        

        //Outsourcing check for variable and return JSX elements on conditionals
        if (actualState.showInputField === true) {
            inputField = (
            <div>       
                {                    
                    actualState.inputFields.map((val,index) => (   
                        <ListElemErrorBoundary key={index}>                   
                            <InputElement key={index} elemValue = {val} name={"input" +  index} onChangeListener={(event) => handleDoublettenIDs(event,index)} />
                        </ListElemErrorBoundary>  
                        )
                    )
                }                
                {actualState.errorMessage!= '' ? <Alert color="danger" >{actualState.errorMessage}</Alert> : null}
                {actualState.successMessage !='' ? <Alert color="success" >{actualState.successMessage}</Alert> : null} 
                <br />                    
                <p><button onClick = { () =>  {
                    handleInputs(props.anzeigeID);    
                    vanishMessage();                
                    }                
                }>absenden</button></p>   
            </div>  
            )
        }
        return inputField;
    }

        return (            
            <div >
                {checkIcon()}  Dubletten eintragen   

                {checkPrerequisites()}                     


            </div>                               
        )      
    }

export default DubletteComponent

Мой компонент InputElement:

const inputElement = (props) => (
    <p>
        <input 
            ref={props.ref}
            value ={props.elemValue}
            name={props.name}
            type="number" 
            max="2147483647"
            placeholder="Doubletten-ID" 
            onChange={props.onChangeListener}>            
        </input>
    </p>


)    

export default inputElement

1 Ответ

0 голосов
/ 13 мая 2019

Проблема в том, что вы не можете передать ref из родительского компонента в дочерний компонент.В новой версии реакции вы можете добиться этого с помощью API forwardRef.Используйте его, как показано ниже, если вы находитесь в версии реакции @ 16.

import React from 'react'

const inputElement = React.forwardRef(props) => (
    <p>
        <input 
            ref={props.ref}
            value ={props.elemValue}
            name={props.name}
            type="number" 
            max="2147483647"
            placeholder="Doubletten-ID" 
            onChange={props.onChangeListener}>            
        </input>
    </p>
)  

//To focus textinput

this.inputref.focus();

Удачного кодирования:)

...