繁体   English   中英

React:通过引用访问动态创建的元素的属性

[英]React: Access properties of dynamically created elements by refs

我有5个输入元素的动态创建的列表。 现在,当我在React中单击一个“加号”图标元素(来自IonicIcons)时,我希望这些输入字段中的第一个成为焦点。

我的输入清单:

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;
    }

我可能应该将我的引用放在列表项上,但是,我猜对于每个新的列表元素,此引用都会被“覆盖”,因为我只有一个引用。 我是否应该执行类似输入键查询的操作,以找出这是哪个列表键输入元素,并且如果它是第一个输入键索引,那么我应该对该输入元素执行聚焦吗?

然后,如何设置方法showInputField的toggleInput()方法中的第一个输入元素呢? 是否可以通过某种方式要求输入元素引用的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

问题是您无法将ref从父组件传递到子组件。 在新版本的react中,您可以使用forwardRef api来实现。 如果您使用的是React @ 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();

快乐的编码:)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM