0

I have a 'fileUpload' component which I am passing into a form in my React App.

I want to have the ability to set a unique ref for each input element in my for loop and then pass this ref to a delete button to remove the file.

FileUploadComponent

const FileUpload = ({ addFile, runClick }) => {
          const uploadButton = [];
          const myRefs = React.useRef([]);
        
          for (let i = 1; i < 6; i += 1) {
            uploadButton.push(
              <div key={i}>
                <input
                  type="file"
                  id={`file${i}`}
                  ref={myRefs.current[i] ?? React.createRef()}
                  name={`file${i}`}
                  onChange={addFile}
                />
                <RemoveButton type="button" onClick={() => removeFile()}>
                  X button{i}
                </RemoveButton>
              </div>
            );
          }
    
      return uploadButton;
    };
    
    export default FileUpload;

FormComponent

//working without using the FileUploadComponent and setting/passing the ref manually

<InputField className="col">
        <input
          type="file"
          id="file3"
          name="file3"
          ref={ref3}
          onChange={addFile}
        />
        <RemoveButton type="button" onClick={() => removeFile(ref3)}>
          X
        </RemoveButton>
      </InputField>

// trying to have the ref be automatically assigned and passed to delete button

<InputField className="col">
    <FileUpload addFile={addFile} runClick={() => removeFile()} />
  </InputField>
1

2 Answers 2

1

You can create an array of refs before the loop, using Array.fill():

const myRefs = useRef(new Array(6).fill(createRef()));

And use it in the loop like:

<input type="file" ref={myRefs[i]}/>
Sign up to request clarification or add additional context in comments.

1 Comment

I can see that the refs being created, but not sure this is allowing me to pass the same value into the removeFile click event <RemoveButton type="button" onClick={() => runClick(myRefs[i])}> And then passing to runClick={i => runClick(i)} I can't see them in the function const runClick = i => { console.log('run click', i); };
0

if you don't know how many ref will be defined, you should use RefCallback

there is its type definition in React

type RefCallback<T> = { bivarianceHack(instance: T | null): void  }["bivarianceHack"];
type Ref<T> = RefCallback<T> | RefObject<T> | null;

the RefCallback can pass a instance to you, and then you can use only one React ref to hold all children componends' ref, e.g.

function Parent(){
  const attachmentRefs = useRef({});
  
  return <>
    <Child ref={(instance)=>{
        // before hold the instance, you can check the attachmentRefs.current first.
        //  so that the variable name can be determined in advance
        attachmentRefs.current.childA = instance
        }} />
    <Child ref={(instance)=>{
        // same logic as last one
        attachmentRefs.current.childB = instance
    }} />
    </>
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.