TypeError: Cannot read properties of undefined (reading 'map') React JS and Sanity - sanity

When I try to run the code it gives me this error=
TypeError: Cannot read properties of undefined (reading 'map')
I dont know how to solve this
import React from 'react'
import { Tweet } from '../typings'
import TweetBox from './TweetBox'
import TweetComponent from '../components/Tweet'
interface Props {
tweets: Tweet[]
}
function Feed({ tweets }: Props) {
return (
<div className='col-span-7 lg:col-span-5 border-x'>
<div className="flex items-center justify-between">
<h1 className="p-5 pb-0 text-xl font-bold">Home</h1>
<RefreshIcon className='h-8 w-8 cursor-pointer text-twitter mr-5 mt-5 transition-all duration-500 ease-out hover:rotate-180 active:scale-125'/>
</div>
<div>
<TweetBox />
</div>
{/* Feed */}
<div>
{tweets.map((tweet) => (
<TweetComponent key={tweet._id} tweet={tweet} />
))}
</div>
</div>
)
}
export default Feed ```

tweets array that you try to map is probably empty on render.

go to your index.tsx file and make sure when you are calling you feed component, you push the tweets prop through:
<Feed tweets={tweets}/>
here is the full index.tsx file below
import type { GetServerSideProps, NextPage } from 'next'
import Head from 'next/head'
import Image from 'next/image'
import Feed from '../components/Feed'
import Sidebar from '../components/Sidebar'
import Widgets from '../components/Widgets'
import { Tweet } from '../typings'
import { fetchTweets } from '../utils/fetchTweets'
interface Props{
tweets: Tweet[]
}
const Home = ({tweets}: Props) => {
console.log(tweets)
return (
<div className="lg:max-w-6xl mx-auto max-h-screen overflow-hidden">
<Head>
<title>Twitter 2.0</title>
</Head>
<main className='grid grid-cols-9'>
<Sidebar/>
<Feed tweets={tweets}/>
<Widgets />
</main>
</div>
)
}
export default Home
export const getServerSideProps: GetServerSideProps = async (context) => {
const tweets = await fetchTweets()
return {
props: {
tweets,
}
}
}

Related

PrismicRichText not displaying anything

I have the following barebones component:
<template>
<div v-for="blog in blogs">
<h1 class="text-lg font-medium">{{ blog.title[0].text }}</h1>
<div v-if="blog">
<PrismicRichText :field="blog.body" />
</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from "vue";
import { usePrismic } from "#prismicio/vue";
import { PrismicRichText } from "#prismicio/vue";
const { client, predicate } = usePrismic();
const blogs = ref({});
async function getContent() {
const res = await client.getByType("post");
blogs.value = res.results.map((blog: any) => blog.data);
}
onMounted(getContent);
</script>
<style scoped></style>
When running this, the title is displayed just fine, but the body isn't displayed at all. I see the two nested div's being displayed, but there's no content. When logging the body, it is looking correctly, an array of objects. What am I doing wrong here?

Integrating Google Sign-In into your web app - migrating to the new library

So am practicing building this app, and I have integrated a Google sign-in using the Google Developers console. The problem is that I am getting this error on my console:
{
"error": "idpiframe_initialization_failed",
"details": "You have created a new client application that uses libraries for user authentication or authorization that will soon be deprecated. New clients must use the new libraries instead; existing clients must also migrate before these libraries are deprecated. See the Migration Guide for more information."
}
When I click the sign-in button another error then prints on my console as a second error:
{
"error": "popup_closed_by_user"
}
This is how my Login.jsx file looks like
import React from 'react';
import { GoogleLogin } from 'react-google-login';
import { useNavigate } from 'react-router-dom';
import { FcGoogle } from 'react-icons/fc';
import shareVideo from '../assets/share.mp4';
import logo from '../assets/logowhite.png';
import { client } from '../client';
const Login = () => {
const navigate = useNavigate();
const responseGoogle= (response) => {`
console.log(response)
}
return (
<div className='flex justify-start items-center flex-col h-screen'>
<div className='relative w-full h-full'>
<video
src={shareVideo}
type='video/mp4'
loop
controls={false}
muted
autoPlay
className='w-full h-full object-cover'
/>
<div className='absolute flex flex-col justify-center items-center top-0 right-0 left-0 bottom-0 bg-blackoverlay'>
<div className='p-5' >
<img src={logo} width='130px' alt='logo' />
</div>
<div className='shadow-2xl' >
<GoogleLogin
clientId={process.env.REACT_APP_GOOGLE_API_TOKEN}
render={(renderProps) => (
<button
type='button'
className='bg-mainColor flex justify-center items-center p-3 rounded-lg cursor-pointer outline-none'
onClick={renderProps.onClick}
disabled={renderProps.disabled}
>
<FcGoogle className='mr-4' /> Sign in with Google
</button>
)}
onSuccess={responseGoogle}
onFailure={responseGoogle}
cookiePolicy='single_host_origin'
/>
</div>
</div>
</div>
</div>
)
}
export default Login
client.js
import sanityClient from '#sanity/client'
import imageUrlBuilder from '#sanity/image-url'
export const client = sanityClient({
projectId: process.env.REACT_APP_SANITY_PROJECT_ID,
dataset: 'production',
apiVersion: '2021-11-16',
useCdn: true,
token: process.env.REACT_APP_SANITY_TOKEN,
ignoreBrowserTokenWarning: true
})
const builder = imageUrlBuilder(client);
export const urlFor = (source) => builder.image(source);
App.js
import React from 'react'
import { Routes, Route, useNavigate } from 'react-router-dom';
import Login from './components/Login';
import Home from './container/Home';
const App = () => {
return (
<Routes>
<Route path="Login" element={<Login />} />
<Route path="/*" element={<Home />} />
</Routes>
)
}
export default App
index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import { BrowserRouter as Router} from 'react-router-dom'
import App from './App';
import './index.css';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<Router>
<App/>
</Router>,
);
.env
REACT_APP_GOOGLE_API_TOKEN = /*Sorry cannot show the token to you*/.apps.googleusercontent.com
REACT_APP_SANITY_PROJECT_ID = /*same here*/
REACT_APP_SANITY_TOKEN = /*same here*/
Home.jsx
import React from 'react'
const Home = () => {
return (
<div>
Home
</div>
)
}
export default Home

How to get images from assets folder?

I'm beginner and I currently learn vue.js. I try to create a carousel slider but I can't get my images from the assets folder. I don't find any solution that it helps me to solve the problem. Can anyone help me, why I don't see on the site?
<template>
<div class="container">
<div class="title">Projects</div>
<Carousel class="carousel">
<Slide v-for="(slide, index) in carouselSlide" :key="index">
<div class="slide-info">
<img :src="require(`../assets/${slide}.jpg`)" />
</div>
</Slide>
</Carousel>
</div>
</template>
<script>
import Carousel from "../utility-components/Carousel.vue";
import Slide from "../utility-components/Slide.vue";
export default {
setup() {
const carouselSlide = ["bg-1", "bg-2", "bg-3"];
return carouselSlide;
},
components: { Carousel, Slide },
};
</script>
enter image description here
I found the solution. This code (require) doesn't exist in vue.js 3:
<img :src="require(`../assets/${slide}.jpg`)" />
Run: npm run build and you'll get dist folder where you can save your images then call from there. It works for me.
So the solution is:
<template>
<img :src="picture.pic" />
</template>
<script>
import { ref } from "vue";
const loadImage = async () => {
return new Promise((resolve) => {
resolve({
pic: "dist/assets/bg-1.jpg",
});
});
};
};
export default {
async setup() {
const picture = ref(await loadImage());
return {
picture,
};
},
};
</script>

Vue components not loading

I was given this problematic codebase, where the Vue components aren't loading in.
Vue is mounting, but without any components.
This is a Laravel 5.7 app, using blade templates with some Vue added in.
This is the initial code:
import 'babel-polyfill'
import loadClientScripts from './load-client-scripts'
import 'bootstrap-material-design/js/'
// Vue & axios
import Vue from 'vue'
import { axios } from '../axios-config'
import BootstrapVue from 'bootstrap-vue/dist/bootstrap-vue.esm'
import { createLocales } from '../vue-i18n-config'
import Noty from 'noty'
//Components
import signInForm from './components/SignInForm'
import signUpForm from './components/SignUpForm'
import forgotPassForm from './components/ForgotPassForm'
// import RegisterToAgency from './components/RegisterToAgency'
import SendEmailForm from './components/SendEmailForm'
import AgencyServiceCategories from './components/AgencyServiceCategories'
import DropdownWithCheckboxes from './components/DropdownWithCheckboxes'
import LasiCoalitionAgencies from './components/LasiCoalitionAgencies'
import ServiceProviders from "./components/ServiceProviders";
import ServiceProvider from "./components/ServiceProvider";
import vSelect from "vue-select";
window.axios = axios
Vue.component('v-select', vSelect)
// Bootstrap Vue
Vue.use(BootstrapVue)
export function createApp() {
const i18n = createLocales(window.locale)
// Components
Vue.component('sign-in-form', signInForm)
Vue.component('sign-up-form', signUpForm)
Vue.component('forgot-pass-form', forgotPassForm)
// Vue.component('register-to-agency', RegisterToAgency)
Vue.component('send-email-form', SendEmailForm)
Vue.component('agency-service-categories', AgencyServiceCategories)
Vue.component('dropdown-with-checkboxes', DropdownWithCheckboxes)
Vue.component('lasi-coalition-agencies', LasiCoalitionAgencies)
Vue.component('service-providers', ServiceProviders)
Vue.component('service-provider', ServiceProvider)
new Vue({
i18n
}).$mount('#app')
}
sign in form component for example:
<template>
<div>
<b-form
id="sign-in-form"
#submit="onSubmit"
>
<div class="form-group">
<b-form-input
id="sgi-email"
v-model="model.email"
required
name="email"
:state="state('email')"
type="email"
:placeholder="$t('validation.attributes.email_address')"
/>
<b-form-feedback>{{ feedback('email') }}</b-form-feedback>
</div>
<div class="form-group mb-3">
<b-form-input
id="sgi-password"
v-model="model.password"
required="required"
name="password"
:state="state('password')"
type="password"
:placeholder="$t('validation.attributes.password')"
/>
<b-form-feedback>{{ feedback('password') }}</b-form-feedback>
</div>
<div class="form-group my-0">
<a
class="text-opacity forgot-pass-link"
href="#"
>
{{ $t('labels.user.password_forgot') }}
</a>
</div>
</b-form>
</div>
</template>
<script>
console.log('IM HIT')
export default {
name: 'SignInForm',
data() {
return {
model: {
email: '',
password: ''
},
validation: {}
}
},
mounted() {
this.test()
},
methods: {
test() {
console.log("test")
},
feedback(name) {
if (this.state(name)) {
return this.validation.errors[name][0]
}
},
state(name) {
return this.validation.errors !== undefined &&
this.validation.errors.hasOwnProperty(name)
? 'invalid'
: null
},
onSubmit(evt) {
evt.preventDefault()
window.axios
.post('/login', this.model)
.then(response => {
location.href = '/app'
})
.catch(e => {
if (e.response.status === 422) {
this.validation = e.response.data
return
}
})
}
}
}
</script>
Any ideas help!
in the example sign in form, the console does output the "Im hit" that I had placed to ensure that things were loaded.
Thanks
Are you at any point rendering anything with that Vue instance?
Try passing a component to its render function like so:
// lets pretend you've imported a component from some file App.vue up here and called the component simply 'App'
// e.g.: const App = require('./App.vue') or import App from './App.vue';
Vue.use(BootstrapVue)
export function createApp() {
const i18n = createLocales(window.locale)
// Components
Vue.component('sign-in-form', signInForm)
Vue.component('sign-up-form', signUpForm)
Vue.component('forgot-pass-form', forgotPassForm)
// Vue.component('register-to-agency', RegisterToAgency)
Vue.component('send-email-form', SendEmailForm)
Vue.component('agency-service-categories', AgencyServiceCategories)
Vue.component('dropdown-with-checkboxes', DropdownWithCheckboxes)
Vue.component('lasi-coalition-agencies', LasiCoalitionAgencies)
Vue.component('service-providers', ServiceProviders)
Vue.component('service-provider', ServiceProvider)
new Vue({
i18n,
render: createElement => createElement(App) // needs a render function
}).$mount('#app')
}

Unable to implement Materialize-CSS initialization scripts with NextJS

I'm using Materialize CSS to style a web app I'm working on. Am building the app using NextJS with ReactJS. I have already styled the navbar using the classes defined in the Materialize CSS file. However, I'm unable to implement the responsive sidebar functionality using the prescribed initialization script as instructed on the Materialize website.
My Navbar component (./components/Navbar.js) looks like this:
import React, { Component, Fragment } from 'react';
import Link from 'next/link';
import $ from 'jquery';
class Navbar extends Component {
constructor(props) {
super(props)
this.props = props;
}
componentDidMount = () => {
document.addEventListener('DOMContentLoaded', function() {
var elems = document.querySelectorAll('.sidenav');
var instances = M.Sidenav.init(elems, options);
});
}
render() {
return (
<Fragment>
<nav>
<div className="nav-wrapper blue">
<Link prefetch href='/'>
Project Coco
</Link>
<i className="material-icons">menu</i>
<ul id="nav-mobile" className="right hide-on-med-and-down">
<li>
<Link prefetch href='/'>
<a>Home</a>
</Link>
</li>
<li>
<Link prefetch href='/about'>
<a>About</a>
</Link>
</li>
<li>
</li>
</ul>
</div>
</nav>
{/* Sidenav markup */}
<ul className="sidenav" id="slide-out">
<li>
<Link prefetch href='/'>
<a>Home</a>
</Link>
</li>
<li>
<Link prefetch href='/about'>
<a>About</a>
</Link>
</li>
</ul>
</Fragment>
);
}
}
export default Navbar;
As is obvious, this functionality (sidebar) needs JQuery. So I already have it added via yarn and am invoking it using import $ from 'jquery'. But upon running, it throws an error saying sidenav is not a function.
I even tried entirely doing away with JQuery and just going for the vanilla JS version of the initialization script in componentDidMount:
document.addEventListener('DOMContentLoaded', function() {
var elems = document.querySelectorAll('.sidenav');
var instances = M.Sidenav.init(elems, options);
});
But this time, although no error, the functionality still refuses to work and clicking on the hamburger menu doesn't trigger the sidenav, which it should.
The entire code repo is up on Github for reference and the prototype app is live at schandillia.com. Any solutions?
P.S.: It seems the problem is that the initialization code in ComponentDidMount gets executed before MaterializeCSS.js (being called as an external file), on which it depends. Any work around this could be a potential solution, although that's just an assumption.
You need to import materialize-css into your component. Sadly, if you try to do import 'materialize-css' you'll get a window is undefined error. This is because Next.js is universal, which means it executes code first server-side where window doesn't exist. The workaround I used for this problem is the following:
Install materialize-css if you haven't:
$ npm i materialize-css
Import materialize-css into your component only if window is defined:
if (typeof window !== 'undefined') {
window.$ = $;
window.jQuery = $;
require('materialize-css');
}
Then, in your componentDidMount method:
componentDidMount = () => {
$('.sidenav').sidenav();
}
So your component looks like this:
import React, { Component, Fragment } from 'react';
import Link from 'next/link';
import $ from 'jquery';
if (typeof window !== 'undefined') {
window.$ = $;
window.jQuery = $;
require('materialize-css');
}
class Navbar extends Component {
constructor(props) {
super(props)
this.props = props;
}
componentDidMount = () => {
$('.sidenav').sidenav();
}
render() {
return (
<Fragment>
<nav>
...
</nav>
{/* Sidenav markup */}
<ul className="sidenav" id="slide-out">
...
</ul>
</Fragment>
);
}
}
export default Navbar;
Sources: Next.js FAQ and this issue.
How about this one:-
_app.tsx
import 'materialize-css/dist/css/materialize.min.css';
import '../styles/globals.css';
function MyApp({ Component, pageProps }) {
return <Component {...pageProps} />;
}
export default MyApp;
index.tsx
import React, { useEffect } from 'react';
const Index = () => {
useEffect(() => {
const M = require('materialize-css');
M.toast({ html: 'worlds' });
}, []);
return (
<div className='container'>
<h1>hello</h1>
</div>
);
};
export default Index;