Where is wrong in my function-based react code

Hello,

I changed my class-based code to functional. I’m sure there are many mistakes. Can you please inform me which parts of wrong?


import React, { Component } from 'react';
import { Redirect } from "react-router-dom";
import React, { useState } from "react";

export function ImageUpload1() {

    const [redirect, setRedirect] = useState(null);
    const [selectedFile, setSelectedFile] = useState(null);
    const [description, setDescription] = useState(null);
    const [uploadResult, setUploadResult] = useState(null);
    const [selectedFileName, setSelectedFileName] = useState(null);

    getList = (selectedFile) => {
        fetch('api/Image')
            .then(response => response.json())
            .then(data => setSelectedFile({ fileIdList: data }));
    };
    useEffect(() => {

        getList();
    });

    onFileChange = selectedFile => {

        selectedFile: event.target.setSelectedFile[0],
            selectedFileName: event.target.setSelectedFileName[0],
    };

    onDescriptionChange = description => {

        setDescription: event.target.value,
    };
    onFileUpload = async (selectedFile, selectedFileName, uploadResult) => {

        const formData = new FormData();

        formData.append(
            "ImageData.File",
            selectedFile,
            selectedFileName
        );



        fetch('/api/Image', {
            method: 'POST',
            body: formData
        }).then(resposne => resposne.json())
            .then(data => {
                console.log(data);
                //this.setState({ uploadResult: "File " + data.fileName + " successfully uploaded." });
                setUploadResult: "File" + data.fileName + "successfully uploaded";
                this.getList();
            });
    }

    onNavToEditor = async (redirect) => {

        this.onFileChangeName();

        //this.setState({ redirect: "/ImageEditor" });
        //    this.setState({ selectedFileName: });

        setRedirect: "/ImageEditor";

    };
    listItems = () => {
        const listItems = this.state.fileIdList.map((item) =>
            <div key={item.imageId.toString()}>
                <img src={"/api/Image/DownloadImage/" + item.imageId}
                    alt={item.fileName}
                    className="img-thumbnail"
                    height="100" width="100" />
            </div>
        );
        return (<div>{listItems}</div>);
    };

    return (

        <div>
            <div style={mystyle} onClick={onNavToEditor} />
            <h1>File Upload Demo</h1>
            <div >{this.state.uploadResult} onClick={onNavToEditor}</div>
            <div>
                <input type="file" onChange={FileChange} />
                <input type="text" value={this.state.value} onChange={DescriptionChange} />
                <button onClick={FileUpload}>
                    Upload!
                    </button>

            </div>

            <div onClick={NavToEditor}>

                {listItems()}

            </div>

        </div>




    );

};

regards,
Saeed

So that we don’t have to spend a lot of time digging through your code, can you explain what is wrong? What is happening that you don’t want to happen, or what is not happening that you do want to happen. This would be very hard for us to test since we don’t have access to your api.

This component upload files and then show the uploaded file in a div. I use a template for react/ASP core.

But know the code has problem.
The class-base code works well.

Here comes the class-based code:

You didn’t answer my question.

I get this error:

Failed to compile

./src/components/ImageUpload.jsSyntax error: Identifier 'React' has already been declared (5:8)  3 | import React, { Component } from 'react';  4 | import { Redirect } from "react-router-dom";> 5 | import React, { useState } from "react";    |        ^  6 |   7 | export function ImageUpload1() {  8 |

This error occurred during the build time and cannot be dismissed.

it can not runing,

Please inform me.

You didn’t think that was relevant information?

I don’t understand. It is telling us exactly what the problem is - that React was already declared. It is showing us exactly what line. It is even pointing the the offending import. On that output we can see two lines above where it is already imported.

Which part of that are you not understanding? What can we explain to make this make sense?

Reread this again closely:

import React, { Component } from 'react';
import { Redirect } from "react-router-dom";
import React, { useState } from "react";

Read the first import on the first line and the first import on the last line.

You sent me this in a PM:

I’m trying to convert my class-based component to functional.
I become really confused.

Do you think is this statement correct:

  getList = (selectedFile) => {
        fetch('api/Image')
            .then(response => response.json())
            .then(data => setSelectedFile({ fileIdList: data }));
    };
    useEffect(() => {

        getList();
    });

To me, I would expect that getList function to be defined inside the useEffect. That probably doesn’t matter, except in terms of dependencies. That is another point - what are the dependencies? Without an array of dependencies, this will run every render, I think - I’m assuming that you don’t want that. I would expect at least an empty array as the dependency list.

Also, why is selectedFile being passed as a parameter to that function? I don’t understand why it needs that. Also, should selectedFile be an object? Maybe, it just looks odd to me.

1 Like

Hello,
Do you think I have used useEffect hook correctly here?
Otherwise what changes should I make?

useEffect(

    //getList();
    const getList = () => {
        fetch('api/Image')
            .then(response => response.json())
            .then(data => setFileIdList({ fileIdList: data }));
    };
);

thanks,
Saeed

1 Like

You probably don’t want to call this fetch on each render, so you want an empty array as second arguments of your useEffect hook.

From React docs:

If you want to run an effect and clean it up only once (on mount and unmount), you can pass an empty array ( [] ) as a second argument. This tells React that your effect doesn’t depend on any values from props or state, so it never needs to re-run. This isn’t handled as a special case — it follows directly from how the dependencies array always works.

Hope this helps.

useEffect( () => {
getList();
}, [])

getList will be best to be defined outside the hook

You mean I use this:

useEffect( () => {
getList();
}, [])

const getList = () => {
            fetch('api/Image')
                .then(response => response.json())
                .then(data => setFileIdList({ fileIdList: data }));
        };

Is this correct?
Why should I use

[]

thanks,

useEffect call should be below the const getList = () => { ... } definition

Can you please explain more?

Like this, since we are using const the function will have to be declared before use, good practice.

2 Likes

Hello,

Here come my imports:


import React, { Component } from "react";
import { Redirect } from "react-router-dom";
import React, { useEffect, useState } from "react";

but when I run and debug my project I encounter this error:

react_error

Why? can you please inform me.

regards,

Do you see in the error message where it says “Identifier ‘React’ has already been declared”? It’s sort of the same thing as if you do:

let x = 10;
let x = 20;

You can’t declare a variable twice.

React has already been imported on line 3, so you could import your hooks there too:
import React, { Component, useEffect, useState } from ‘react’;

When I change it to"

//import React, { Component } from "react";
import { Redirect } from "react-router-dom";
import React, { useEffect, useState, Component } from "react";

Again see a red line under functions:

onFileChange = e => {


        setSelectedFile(e.target.files[0]);
        setSelectedFileName(e.target.files[0]);
    };

What is your idea?

thanks,

Are these functions defined somewhere? It’s really tough to help you if we can’t see your code. Can you put it somewhere public and give us a link?

Here comes the code:



import React, { Component } from "react";
import { Redirect } from "react-router-dom";
import React, { useEffect, useState, Component } from "react";

export function ImageUpload1() {

    const [redirect, setRedirect] = useState(null);
    const [selectedFile, setSelectedFile] = useState(null);
    const [description, setDescription] = useState(null);
    const [uploadResult, setUploadResult] = useState(null);
    const [selectedFileName, setSelectedFileName] = useState(null);
    const [fileIdList, setFileIdList] = useState(null);


    getList = (selectedFile) => {
        fetch('api/Image')
            .then(response => response.json())
            .then(data => setSelectedFile({ fileIdList: data }));
    };
    useEffect(() => {

        getList();
    });

    onFileChange = e => {


        setSelectedFile(e.target.files[0]);
        setSelectedFileName(e.target.files[0]);
    };

    onDescriptionChange = event => {

        setDescription(event.target.value);
    };
    onFileUpload = async (selectedFile, selectedFileName, uploadResult) => {

        const formData = new FormData();

        formData.append(
            "ImageData.File",
            selectedFile,
            selectedFileName
        );



        fetch('/api/Image', {
            method: 'POST',
            body: formData
        }).then(resposne => resposne.json())
            .then(data => {
                console.log(data);
                this.setState({ uploadResult: "File " + data.fileName + " successfully uploaded." });
                setUploadResult: "File" + data.fileName + "successfully uploaded";
                this.getList();
            });
    }

    //onNavToEditor = async (redirect) => {

    //    //this.onFileChangeName();

    //    //this.setState({ redirect: "/ImageEditor" });
    //    //    this.setState({ selectedFileName: });

    //    setRedirect: "/ImageEditor";

    //};

    onNavToEditor = () => {

        setRedirect: "/ImageEditor";

    };



    listItems = () => {
        const listItems = this.state.fileIdList.map((item) =>
            <div key={item.imageId.toString()}>
                <img src={"/api/Image/DownloadImage/" + item.imageId}
                    alt={item.fileName}
                    className="img-thumbnail"
                    height="100" width="100" />
            </div>
        );
        return (<div>{listItems}</div>);
    };

    return (

        <div>
            <div style={mystyle} onClick={onNavToEditor} />
            <h1>File Upload Demo</h1>
            <div >{this.state.uploadResult} onClick={onNavToEditor}</div>
            <div>
                <input type="file" onChange={FileChange} />
                <input type="text" value={this.state.value} onChange={DescriptionChange} />
                <button onClick={FileUpload}>
                    Upload!
                    </button>

            </div>

            <div onClick={NavToEditor}>

                {listItems()}

            </div>

        </div>




    );

};