How to filter or find a string in an array of strings

Viewed 88

I am trying to filter a collection from Mongo Atlas with string properties: names and urls.

I am then trying to save that filtered value, store and retrieve from Mongo, and send it back to another component.

I am getting a 500 internal server error. I have tried to target the filtered name of the array, I am only returning the full array and not the result of the filter. I have added a name property to my express server and all seems to work fine.

My goal is to use the filter water to display the image that matches and use that value in another component to, then again filter and access the matching image.

I am successful in returning the filtered name in the names array map function which displays name:waterfall <div>name:{urlName}</div, however I am not successful in sending the same filtered value to monogo.

Also, I tried commenting out setName(response.data.name);, but it returns: TypeError: Cannot read property 'filter' of undefined when save button is clicked.

Gallery.js React

import React, { useState, useEffect } from "react";
import { useHistory } from "react-router-dom";
import { isExpired, decodeToken } from "react-jwt";
import Input from "../../Reuseables/reusableInput/Input";
import Container from "react-bootstrap/Container";
import Card from "react-bootstrap/Card";
import Button from "react-bootstrap/Button";
import Form from "react-bootstrap/Form";
import "../css/waterfall.css";
import axios from "axios";

  const Waterfall = () => {
  const [body, setBodyInput] = useState("");
  const [title, setTitleInput] = useState("");
  const [id, setId] = useState("");
  const [url, setUrl] = useState([]);
  const [name, setName] = useState([]);

  const history = useHistory();

  function makeRequest(e) {
    e.preventDefault();
    //gets data from inputs and sends to backend
    axios({
      method: "POST",
      url: "http://localhost:5000/getinput",
      data: {
        body: body,
        title: title,
        // name: name,
      },
    }).then((response) => {
      setId(response.data.data._id);
      // setName(response.data.name);
      console.log(response.data);
    });
  }

  const loadImage = async () => {
    try {
      let res = await axios.get("http://localhost:5000/geturls");
      console.log(res.data)
      setUrl(res.data.map(d=>d.url)); // array of urls
      setName(res.data.map(n=>n.name)); //array of names
    } catch (error) {
      console.log(error);
    }
  };

  useEffect(() => {
    // console.log("use effect working!");
    // function checks login
    }
    loadImage();
  },[history]);

  return (
    <div className="waterfall">
      <Container className="mt-5 ml-auto mr-auto">
        <h1 className="text-center"> Post to
          <span className="text-success"> ShareVerse</span>
        </h1>
        <Form className="shadow p-3 mb-5 bg-white rounded">
          <Form.Group controlId="formBasicVerse">
          <Form.Label> 
              <h5>Verse Title</h5>
            </Form.Label>
            <Input setInputValue={setTitleInput} 
                   inputValue={title} 
                   inputName={'title'}
                   inputType={"text"}
          />          
            </Form.Group>

          <Form.Group controlId="formBasicVerse">
            <Form.Label>
              <h5>Verse Body:</h5>
            </Form.Label>
            <Input setInputValue={setBodyInput}  
                   inputValue={body} 
                   inputName={'body'}
                   inputType={"text"}
          />      
          </Form.Group>
          <div className="">
            <Card className="bg-dark text-white">
            {name.filter(name => name.includes('water')).map((urlName) => (
            <div>name:{urlName}</div>
            ))}
            
            {url.filter(name => name.includes('water')).map((urlData) => (
            <Card.Img name={url.name} src={urlData} alt="Card image" />
            ))}
              <Card.ImgOverlay> 
                <Card.Title className="text-center mt-5">
                  <h1>{title}</h1>
                </Card.Title>
                <Card.Title className="text-center mt-5">{body}</Card.Title>
              </Card.ImgOverlay>
            </Card>
            <div>
              <Button 
                  className=" saveImageBtn mt-3" 
                  type="submit" onClick={makeRequest}
              > Save
              </Button>

              <div>
              <Button
                className=" saveImageBtn mt-3"
                href={`http://localhost:3000/getverse/${id}`}
              >
                View Post!
              </Button>
              </div>
            </div>
          </div>
        </Form>
      </Container>
    </div>
  );
};

export default Waterfall;

GalleryController.js

exports.PostGalleryInput = async (req, res) => {
    console.log(req.body)
    // res.send("recieved");
    await new Posts(req.body).save( async (err, data) => {
      if (err) {
        // if there is an error send the following response
        res.status(500).json({
          message: "Something went wrong, please try again later.",
        });
      } else {
        // if success send the following response
        res.status(200).json({
          message: "Post Created",
          data,
        });
      }
    });
  };

enter image description here

1 Answers

I think backend API is expecting a string for name in payload not an array of string.

So, you can do: names.find(name => name === "water")

const [names, setNames] = useState([]); // For simplicity, use plural here i.e. names

function makeRequest(e) {
  e.preventDefault();
  axios({
    method: "POST",
    url: "http://localhost:5000/getinput",
    data: {
      body: body,
      title: title,
      name: names.find(name => name === "water"), // Here
    },
  }).then((response) => {
    setId(response.data.data._id);
    console.log(response.data);
  });
}

Now, instead of hard-coding water, you can use a variable there (e.g. if it is stored in any state variable).

Related