Meteor/React: How to integrate react component in main template - javascript

This is how my search page looks like in my meteor application:
/client/main.html
<head>
<title>Search</title>
</head>
<body>
<div class="ui icon input">
<input type="text" placeholder="Search...">
<i class="circular search link icon"></i>
</div>
</body>
I'm completely new to react and I would like to use react for this simple search.
/imports/ui/search.jsx
import React, { Component } from 'react';
export default class Search extends Component {
render() {
return (
<div class="ui icon input">
<input type="text" placeholder="Search...">
<i class="circular search link icon"></i>
</div>
);
}
}
But how do I have to use it for react properly? How do I use that component in the main template? And how can I set this input field centered on the screen?

You'd better check the document and example first.
Here is an example to answer your question.
Html just contains the empty container element.
<script src="https://facebook.github.io/react/js/jsfiddle-integration.js"></script>
<div id="container">
<!-- This element's contents will be replaced with your component. -->
</div>
The App component is the main component. You could use something like Router.
class App extends React.Component {
render() {
return (
<div>
<Search />
</div>
);
}
}
Search component as you made. In above, you could see Search component is used such that way in React.
About style, you can pass style object to component directly or make a css file.
class Search extends React.Component {
render() {
return (
<div class="ui icon input" style={searchContainerStyle}>
<input type="text" style={searchInputStyle} placeholder="Search..." />
<i class="circular search link icon"></i>
</div>
);
}
}
const searchContainerStyle = {
width: '50%',
margin: '0 auto'
}
const searchInputStyle = {
width: '100%'
}
Finally, render App under container element.
React.render(<App />, document.getElementById('container'));

Related

How do I pass an entire image element as a prop in React?

I am getting a JSON response that has an image property for each key. This image property is the entire image element tag with properties. I am trying to pass that down into a child component, but upon attempting to render, it just shows up as plain html text on the page. Is there a way to render it as an actual image tag?
I have attached a screenshot of the JSON response
` <div className="aspect-[3/2] md:aspect-square overflow-hidden">
{props.image}
</div>
<span className="block py-5">{props.name}</span>`
You could use dangerouslySetInnerHTML but you'll have to wrap it in a span or div or something:
// Example class component
class Thingy extends React.Component {
render() {
const {source} = this.props;
console.log("rendered");
return (
<span dangerouslySetInnerHTML={{ __html: source }} />
);
}
}
// Render it
ReactDOM.render(
<Thingy source={`<img src="https://images.unsplash.com/photo-1490730141103-6cac27aaab94?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1000&q=80" />`} />,
document.getElementById("root")
);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.development.js"></script>

How to manipulate/modify external UI component library in react?

I'm working on an app that uses an open source calendar library that renders the day as spans. I wish to change certain days to another button component library.
Example snippet of the external library usage
import Calendar, { CalendarView } from 'calendar' // import component
import '../styles/index.css'; // import styles
const CalendarComponent: FC<CalendarComponentType> = ({
{...props}
}) => {
return (
<>
<Calendar
onEventClick={onEventClick}
onNewEventClick={onNewEventClick}
events={[]}
initialDate={new Date().toISOString()}
hourHeight={60}
initialView={CalendarView.WEEK}
disabledViews={[CalendarView.DAY]}
onSelectView={onSelectView}
selectedView={selectedView}
onPageChange={onPageChange}
timeFormat={'24'}
weekDayStart={'Monday'}
calendarIDsHidden={['work']}
language={'en'}
/>
</>
);
}
export default CalendarComponent;
it renders a deeply nested HTML component
<div class="CalendarContainer">
<div class="CalendarNavigation">
... content
</div>
<div class="CalendarBody">
<div class="CalendarTimeTable">
<div id="Calendar_day__2022-08-01" class="DayViewOneDay">
<span class="Calendar_text__day">01</span>
... content
</div>
<div id="Calendar_day__2022-08-02" class="DayViewOneDay">
<span class="Calendar_text__day">02</span>
... content
</div>
<div id="Calendar_day__2022-08-03" class="DayViewOneDay">
<span class="Calendar_text__day">03</span>
... content
</div>
<div id="Calendar_day__2022-08-04" class="DayViewOneDay">
<span class="Calendar_text__day">04</span>
... content
</div>
<div id="Calendar_day__2022-08-05" class="DayViewOneDay">
<span class="Calendar_text__day">05</span>
... content
</div>
</div>
</div>
</div>
For example, I want to modify certain days from <span> to button component from another component library so it becomes
<div id="Calendar_day__2022-08-02" class="DayViewOneDay">
<CustomButton>
... content
</CustomButton>
... content
</div>
Is there any way to do this without modifying the source library?

reusing the "add todo" component as "edit todo" in preact

I just copied the todo from w3 schools and added some functionality with preact. So far all working fine with functional components. Don't mind the string literals and the inline styles.
What I am not getting is:
I have the empty "form" for adding todos:
const EditTodo = (props) => {
return html`
<h2 style="margin:5px;">My To Do List</h2>
<input ref=${todoTitleRef} type="text" placeholder="Title..." value=${props.todo.title}/>
<textarea value=${props.todo.content} ref=${todoContentRef} style="margin-top: 20px;" type="text" id="myText" placeholder="Text..."></textarea>
`;
}
I wanted to reuse it for editing a todo. So my question is: How can I add a hook in the root component to re-render the EditTodo but passing the todo that was clicked to edit?
this is the main component:
return html`
<div class="app">
<div id="myDIV" class="header">
${html`<${EditTodo} todo=${{}}/>`}
<div style="margin-top: 40px;"><span class="addBtn" onClick=${addTodo}>Add</span></div>
</div>
<ul id="myUL">
${todos.map((todo) => html`<${TodoItem} todo=${todo}/>`)}
</ul>
</div>
`;
For anyone wondering,
added the const after the reducer:
const editingTodo = todos.filter(todo=>todo.isEditing);
then changed the prop todo of the main editTodo to:
${html`<${EditTodo} todo=${editingTodo.length>0?editingTodo[0]:{}}/>`}

Render different html depending on index of object in react

In my meteor project I have a collection called auctions. Using react I wish to render 3 columns of this auctions with unlimited number of rows. To accomplish this I thought it would be possible to send the index of the object but I have no idea how to do this. Another problem is that it shows an error with the html code since I'm not closing the 'div' tag.
This is my App.js:
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import { withTracker } from 'meteor/react-meteor-data';
import { Auctions } from '../api/auctions.js';
import Auction from './Auction.js';
//App component - represents the whole app
class App extends Component {
renderAuctions() {
return this.props.auctions.map((auction, index) => (
<Auction key={auction._id} auction={auction} index={index} />
));
}
render() {
return (
<div className="container section">
<div className="row">
{this.renderAuctions()}
</div>
</div>
);
}
}
export default withTracker(() => {
return {
auctions: Auctions.find({}).fetch(),
};
})(App);
And my Auction.js:
import React, { Component } from 'react';
//Task component - resepresnts a single todo item
export default class Auction extends Component {
render() {
if(index % 3 === 0) {
return (
</div> /* Shows an erros here because of closing tag*/
<div className="row">
<div className="col s4 ">
<div className="card">
<div className="card-image">
<img src="images/logo.png" />
</div>
<div className="card-content">
<span className="card-title">
{this.props.auction.auctionName}
</span>
<p>
I am a very simple card. I am good at containing small bits of information.
I am convenient because I require little markup to use effectively.
</p>
</div>
<div className="card-action">
This is a link
</div>
</div>
</div>
);
} else {
<div className="col s4">
<h1>Brincoooo</h1>
<div className="card">
<div className="card-image">
<img src="images/logo.png" />
</div>
<div className="card-content">
<span className="card-title">
{this.props.auction.auctionName}
</span>
<p>
I am a very simple card. I am good at containing small bits of information.
I am convenient because I require little markup to use effectively.
</p>
</div>
<div className="card-action">
This is a link
</div>
</div>
</div>
}
}
}
Any time you return HTML from a render function it needs to be self contained and have balanced tags. That's the way React works, and why it's giving you an error.
Instead of trying to group 3 auctions at a time, you could think of using flexbox instead. With flexbox you simply render all of your auctions, and it looks after the wrapping automatically for you. Users with wider screens will see more than 3 columns, and users on mobile will see probably one when in portrait mode.
If you want to learn about flexbox, there is a cute tutorial here: https://flexboxfroggy.com/ There are plenty of tutorials around if you don't like that one, such as this: https://scotch.io/tutorials/a-visual-guide-to-css3-flexbox-properties
I'll let you do the work from here

React: Unterminated JSX contents

Why do I get the error Unterminated JSX contents for the closing div-element? What am I doing wrong?
export default class Search extends Component {
render() {
return (
<div class="ui icon input">
<input type="text" placeholder="Search...">
<i class="circular search link icon"></i>
</div>
);
}
}
Issue is, you forgot to close your input element, in JSX you have to close all the opened tags properly like in XML.
As per DOC:
JSX is a XML-like syntax extension to ECMAScript without any defined
semantics. It's intended to be used by various preprocessors
(transpilers) to transform these tokens into standard ECMAScript.
One more thing, class is a reserved keyword, to apply any css class instead of using the class keyword, use className.
Try this:
export default class Search extends Component {
render() {
return (
<div className="ui icon input">
<input type="text" placeholder="Search..."/>
<i className="circular search link icon"></i>
</div>
);
}
}
Your input JSX element is not terminated, it is missing a closing tag.
And class is a reserved name in Javascript. You need to use the className prop instead.
<div className="ui icon input">
<input type="text" placeholder="Search..." />
<i className="circular search link icon"></i>
</div>
import React, { Component } from 'react';
class Counter extends Component {
render() {
return (
<div>
<h1>Hello World</h1>
<button>Increment</button>
</div>
);
}
}
export default Counter;

Categories