How can align my elements on the left side of the page? - javascript

I am a new programmer and I recently started following a music-player tutorial, and am experiencing a couple of styling issues with it.
Project Overview:
As previously described, it is a music-player project made with create-react-app. The objective is to click the image of the song of your choosing, and for the song to be played for you.
The Problem:
Currently they are in a column, aligned in the center. How can I line the images of the songs on the left side of the page? I tried doing a couple of things on my css file named Turkish.css(shown below) like:
align-items: flex-start
justify-items: flex-start;
However they did not do anything.
The Code:
Turkish.js (the music-player file):
import React, { Component,useRef, setStatus, status } from 'react';
import './Turkish.css';
import turk1 from "./music/turk1.mp3";
import turk2 from "./music/turk2.mp3"
import turk3 from "./music/turk3.mp3"
import turk4 from "./music/turk4.mp3"
export default function Turkish() {
const data = [
{ imgSrc: 'turk1.png', audioSrc: turk1 },
{ imgSrc: 'turk2.png', audioSrc: turk3 },
{ imgSrc: 'turk3.png', audioSrc: turk4 },
{ imgSrc: 'turk4.png', audioSrc: turk2 },
];
return (
<div className='Turkish'>
<ol>
{data.map(({ imgSrc, audioSrc }) => (
<MediaComponent imgSrc={imgSrc} audioSrc={audioSrc} />
))}
</ol>
</div>
);
}
const MediaComponent = ({ imgSrc, audioSrc }) => {
const audioRef = useRef(null);
const toggleAudio = () =>
audioRef.current === null
? console.log("Audio component is not loaded yet.")
: audioRef.current.paused
? audioRef.current.play()
: audioRef.current.pause();
return (
<ol>
<img src={imgSrc} onClick={toggleAudio} />
<audio
ref={audioRef}
src={audioSrc}
onLoad={() => setStatus({ ...status, isLoaded: true })}
onPlay={() => setStatus({ ...status, isPlaying: true })}
onPause={() => setStatus({ ...status, isPlaying: false })}
onError={() => setStatus({ ...status, error: true })}
/>
</ol>
);
};
Turkish.css
.Turkish ol {
cursor: grab;
border: solid;
border-color: #303030;
border-width: 0.01px ;
border-left: transparent;
border-right: transparent;
border-bottom: transparent;
}
Let me know what you think!
Thank You,
-Zpo

Related

Updating State via onClick, in a Component

I'm new to StackOverflow and looking forward to contributing back to the community!
My first question, I am trying to make some squares change color on the screeen, after an onClick event. I'm nearly there, but I keep getting an error when I try to update the state, which then should updates the color. Please could you let me know what I'm doing wrong?
App.js
import React from "react"
import boxes from "./boxes"
import Box from "./Box"
export default function App() {
const [squares, setSquares] = React.useState(boxes)
function changeOn() {
console.log(squares)//just checking I'm getting the full object
setSquares({
id: 1, on: false //this was previously [...prev], on: !squares.on
})
}
const squaresElement = squares.map(props => (
<Box key={props.id} on={props.on} onClick={changeOn} />
))
return (
<main>
{squaresElement}
</main>
)
}
Box.js
import React from "react"
export default function Box (props) {
const styles= props.on ? {backgroundColor: "#222222"} : {backgroundColor: "none"}
return (
<div className="box" style={styles} onClick={props.onClick}></div>
)
}
Boxes.js
export default [
{
id: 1,
on: true
},
{
id: 2,
on: false
},
{
id: 3,
on: true
},
{
id: 4,
on: true
},
{
id: 5,
on: false
},
{
id: 6,
on: false
},
]
I hope somebody can easily spot what's wrong here?
I was expecting to see the color of the top left box change to a different color, after a click.
There are two issues:
setSquares needs the whole array, so you need to give it a new squares array
The styling back to None does not work always. better to give it the white color again
Please find the codesandbox
export default function App() {
const [squares, setSquares] = React.useState(boxes);
function changeOn(id) {
setSquares(
squares.map((square) => {
return { ...square, on: id === square.id ? !square.on : square.on };
})
);
}
const squaresElement = squares.map((props) => (
<Box key={props.id} on={props.on} onClick={() => changeOn(props.id)} />
));
return <main>{squaresElement}</main>;
}
And in Box.js
const styles = props.on
? { backgroundColor: "#222222" }
: { backgroundColor: "#fff" };
You're calling setSquares and passing it a single object instead of an array.
On the next render squares.map(...) blows up because squares is the object, and the object doesn't have a map method.
// after this call squares is just this one object
setSquares({
id: 1, on: false
})
Here's a possible implementation that pushes the on/off responsibility into the box component itself.
// generates a list of items (faking your boxes.js)
const boxes = Array.from({length: 9}, (_, id) => ({ id }));
// container element to render the list
function Boxen ({ items }) {
return (
<div className="container">
{items.map((item, idx) => (
<Box item={item} key={idx} />
))}
</div>
)
}
// component for a single box that can toggle its own on/off state
function Box ({item}) {
const [active, setActive] = React.useState();
return (
<div onClick={() => setActive(!active)} className={active ? 'active' : ''}>{item.id}</div>
)
}
ReactDOM.render(<Boxen items={boxes}/>, document.getElementById('root'));
.container {
display: grid;
grid-template-columns: repeat(3, 100px);
grid-template-rows: repeat(3, 100px);
gap: 1em;
}
.container > * {
display: flex;
justify-content: center;
align-items: center;
background: skyblue;
}
.container > .active {
background: slateblue;
color: white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.14.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.14.0/umd/react-dom.production.min.js"></script>
<div id="root"></div>

How to dynamically change style on conditionally rendered element in Svelte

Testing out SvelteKit 1.0 with a basic todo app but I'm unable to make the text strikethrough conditionally. When the user clicks the checkbox on the left of the TodoItem the text should change style to become strikethrough. I logged out the values for completed and textDecoration whenever they change and so I'm fairly confident the data is being passed correctly, the style just isn't changing for some reason.
I tried following the example laid out in the docs here as closely as possible but it's still not working. Here is the code
+page.svelte (Home)
<script lang="ts">
import SearchBar from '$components/SearchBar.svelte';
import TodoItem from '$components/TodoItem.svelte';
let todos = [
{
id: 0,
text: 'first task',
completed: false
}
];
const addTodos = (taskText: string) => {
if (!taskText) return;
todos = [
...todos,
{
id: todos.length,
text: taskText,
completed: false
}
];
console.log(todos);
};
const checkTodo = (id: number) => {
todos[id].completed = !todos[id].completed;
};
</script>
<h1>to-do app</h1>
<SearchBar onAdd={(str) => addTodos(str)} />
{#each todos as todo}
<TodoItem
text={todo.text}
bind:completed={todo.completed}
onCheck={() => checkTodo(todo.id)}
onDelete={() => console.log(`Delete ` + todo.id)}
/>
{/each}
TodoItem.svelte
<script lang="ts">
export let text: string;
export let onDelete: () => void;
export let onCheck: () => void;
export let completed: boolean;
$: textDecoration = completed ? 'line-through' : 'none';
//console log when value changes
$: textDecoration, console.log(textDecoration);
$: completed, console.log(completed);
</script>
{#if text}
<div class="todoContainer">
<input
on:click={() => {
onCheck();
}}
id={`todo-checkbox-` + text}
type="checkbox"
/>
<div style:textDecoration style:textAlign="left">
{text}
</div>
<div on:click={onDelete} on:keypress={onDelete}>x</div>
</div>
{/if}
<style>
.todoContainer {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
height: 50px;
border: 1px solid black;
border-radius: 5px;
margin: 10px 0;
}
</style>
Use dash instead of camelCase with the style:directive (an example seems to be missing in the docs and tutorial)
style:text-decoration={textDecoration}

radio group buttons using ant design dont work

I am experiencing some issues with radio group buttons. Can someone help me with this issue. (your help is much appreciated)
Current Issue: Radio Group are not clickable. Im not sure where I missed up!
Technologies Used: React hooks, styled-components , and design
for the radio buttons.
RadioGroup.js
import React from "react";
import { Radio } from "antd";
import styled from "styled-components";
import { theme } from "constants/theme";
const { royalBlue, black } = theme.colors;
const { medium } = theme.typography.size;
const { display } = theme.typography.font.family;
const StyledRadioGroup = styled(Radio.Group)`
width: 100%;
margin-top: 0.5rem;
text-align: left;
.ant-radio-wrapper {
justify-content: space-between;
padding: ${(props) => props.padding};
white-space: break-spaces;
margin-left: -1.5rem;
span.ant-radio + * {
font-family: ${display};
font-size: ${medium};
color: ${black};
letter-spacing: 0;
}
.ant-radio-inner {
border-color: ${royalBlue};
border-width: 0.2rem;
width: 2.5rem;
height: 2.5rem;
&::after {
background-color: ${royalBlue};
top: 0.2rem;
left: 0.2rem;
}
}
}
`;
const RadioGroup = ({
options,
onChange,
value,
defaultValue,
flex,
padding,
}) => {
return (
<StyledRadioGroup
size="large"
flex={flex}
padding={padding}
onChange={onChange}
value={value}
defaultValue={defaultValue}
>
{options.map((option, index) => (
<Radio value={option.stateKey} key={index}>
{option.value}
</Radio>
))}
</StyledRadioGroup>
);
};
export default RadioGroup;
Navigation.js
import React, { useState, useReducer } from "react";
import styled from "styled-components";
import RadioModal from "components/Feedback/RadioModal";
import RadioGroup from "components/Feedback/RadioGroup";
const renderRadioModal = () => {
const inputLabelsText = [
{
stateKey: "age",
label: "What is your age?",
},
];
const radioButtonOptions = [
{
stateKey: "covidImpact",
value: "I go to work/school normally",
},
{
stateKey: "covidImpact",
value: "I am healthy but in a stay-at-home quarantine",
},
{
stateKey: "covidImpact",
value: "I have mild symptoms but haven't been tested",
},
{
stateKey: "covidImpact",
value: "I am diagnosed with Covid-19",
},
];
const RadioGroupWithLabel = withLabel(() => (
<RadioGroup
onChange={true}
options={radioButtonOptions}
value={true}
padding="1rem 1rem"
size="large"
></RadioGroup>
));
return (
<RadioModal
maskClosable={true}
closable={true}
visible={radioModal}
onClose={() => closeRadioModal()}
transparent
>
<h2 className="title">We are almost done!</h2>
{inputLabelsText.map((label, index) => (
<>
<StyledInput
key={index}
label={label.label}
value={label.stateKey}
onChange={dispatchAction}
></StyledInput>
<RadioGroupWithLabel label={"How has COVID-19 impacted you?"} />
</>
))}
<FeedbackSubmitButton
title="Submit Feedback"
onClick={closeRadioModal}
></FeedbackSubmitButton>
</RadioModal>
);
};
You have onChange={true} and value={true}. You need to handle the onChange and value properly. The value prop needs to match the value in your options that you pass into the radio group.
The options you pass in should be in the structure [{ value, label }, { value, label }]
Then in your onChange you need to handle setting that value + have a place to store it

how can i display round dot for active status in react

In older code of react it just display the text active or in active for an user. Now I want to replace it to red or green small dot how can I do it.
CSS
div .colored-circle {
display: inline-block;
margin-left: 5px;
margin-right: 5px;
margin-bottom: -2px;
border-radius: 50%;
border-style: solid;
border-width: 0.5px;
border-color: black;
height: 20px;
width: 20px;
}
Component:
const ColoredCircle = ({ color }) => {
const styles = { backgroundColor: color };
return color ? (
<Fragment>
<span className="colored-circle" style={styles} />
</Fragment>
) : null;
};
export default ColoredCircle;
Use the same logic you used to show 'active' or 'inactive' and instead of text add a div with css or img of the desired color.
If you happen to use material UI, you can do like this:
import React, { Fragment } from "react";
import { makeStyles } from "#material-ui/core";
const RADIUS_DOT = 1.5;
const useStyles = makeStyles((theme) => ({
circle: {
borderRadius: RADIUS_DOT,
height: RADIUS_DOT * 2,
width: RADIUS_DOT * 2,
padding: 0,
},
}));
const ColoredCircle = ({ color }) => {
const styles = { backgroundColor: color };
const classes = useStyles();
return color ? (
<Fragment>
<span className={classes.circle} style={styles} />
</Fragment>
) : null;
};
export default ColoredCircle;
you can use this package, can be helpful
npm i react-color-circle
import Circle from '#uiw/react-color-circle';
return (
<Circle
colors={[ '#F44E3B' ]}
/>);

Strikethrough a Paragraph in React.js via onClick?

I'm pretty much ready to rip my hair out. So my final project in my Javascript class is an experimental thing with learning React.js, where you do a basic todo list. I got all that done and working, and I can have it add things properly. But my final hurdle is making it so that onclicking the printed paragraph from the button will cause them to give the printed paragraphs the strikethrough property, which can be undone by clicking on it again.
I've looked up everywhere, I've tried other examples from here, and nothing I can think of gets the strikethrough to take place. I tried a basic Javascript function that would do what I wanted if this was an HTML/non-react file, but it breaks the react page when I try to plop it in. So I spent a stupidly long time on a tutorial trying to figure out what to do, and I maybe figured out the step in the right direction? But I still can't get anything to happen and I don't know how to establish an onclick to this.
import React from 'react';
import './App.css';
class App extends React.Component {
setCurrentToDoItem = (toDoItem) => {
console.log("toDoItem", toDoItem);
this.setState({
currentToDoItem: toDoItem
});
};
saveToDoListItem = (toDoItem) => {
this.setState({
toDoList: [...this.state.toDoList,
toDoItem]
});
};
constructor(props) {
super(props);
this.state = {
currentToDoItem: null,
toDoList: [],
strikeThrough: []
};
}
render() {
return (
<div>
<h1>To Do List</h1>
<label>To Do Item: </label>
<input
onChange={(event) => this.setCurrentToDoItem(event.target.value)}>
</input>
<button onClick={() => this.saveToDoListItem(this.state.currentToDoItem)}>
<p>Add Item</p>
</button>
<p>{this.state.currentToDoItem}</p>
<div>
<p>To Do Items</p>
{
this.state.toDoList.map((item, index) => <p key={index}>{item} </p>)
}
</div>
</div>
);
}
}
export default App;
This is my App.js code. As you can see, everything else should work fine, but I have no clue how to add a strikethrough effect to what would result from the this.state.toDoList.map((item, index) => <p key={index}>{item} </p>) bit like I would with a function in normal javascript. How do I make the printed lines strikethrough via onclick, and then how do I undo that by clicking on it again? (I assume with a second onclick) I really just need to know how to get a working strikethrough with this, as everything else is pretty much working.
One of the most comfortable ways to do that is as advised in comments. A really quick way to implement this is to toggle class list. In the code bellow, I added a function crossLine which toggles class name "crossed-line" and adds event listener on mapped to-dos (in render function). Then in your App.css add a line
.crossed-line {
text-decoration: line-through;
}
Here's your edited component code.
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
currentToDoItem: null,
toDoList: [],
strikeThrough: []
};
}
setCurrentToDoItem = toDoItem => {
this.setState({
currentToDoItem: toDoItem
});
};
saveToDoListItem = toDoItem => {
this.setState({
toDoList: [...this.state.toDoList, toDoItem]
});
};
crossLine = event => {
const element = event.target;
element.classList.toggle("crossed-line");
};
render() {
return (
<div>
<h1>To Do List</h1>
<label>To Do Item: </label>
<input
onChange={event =>
this.setCurrentToDoItem(event.target.value)
}
/>
<button
onClick={() =>
this.saveToDoListItem(this.state.currentToDoItem)
}
>
<p>Add Item</p>
</button>
<p>{this.state.currentToDoItem}</p>
<div>
<p>To Do Items</p>
{this.state.toDoList.map((item, index) => {
return (
<p onClick={this.crossLine} key={index}>
{item}{" "}
</p>
);
})}
</div>
</div>
);
}
}
As commented, you will have to keep a handle click and add class to add strikethrough using CSS.
For this I have updated your JSX to:
<p onClick={ () => this.handleClick(index) } className={ item.isComplete ? 'completed' : '' } key={index}>{item.value} </p>
and the signature of toDoItem from string to an object:
{
value: string;
isComplete: boolean
}
and based on this flag, I'm adding class.
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
currentToDoItem: null,
toDoList: [],
strikeThrough: []
};
this.setCurrentToDoItem = this.setCurrentToDoItem.bind(this);
this.saveToDoListItem = this.saveToDoListItem.bind(this);
this.handleClick = this.handleClick.bind(this);
}
setCurrentToDoItem(toDoItem) {
this.setState({
currentToDoItem: toDoItem
});
}
saveToDoListItem(toDoItem) {
this.setState({
toDoList: [...this.state.toDoList, {
value: toDoItem,
isComplete: false
}]
});
}
handleClick(index) {
const {
toDoList
} = this.state;
toDoList[index].isComplete = !toDoList[index].isComplete;
this.setState({
toDoList
});
}
render() {
return (
<div>
<h1>To Do List</h1>
<label>To Do Item: </label>
<input
onChange={(event) => this.setCurrentToDoItem(event.target.value)}>
</input>
<button onClick={() => this.saveToDoListItem(this.state.currentToDoItem)}>
<p>Add Item</p>
</button>
<p>{this.state.currentToDoItem}</p>
<div>
<p>To Do Items</p>
{
this.state.toDoList.map((item, index) =>
<p onClick={ () => this.handleClick(index) } className={ item.isComplete ? 'completed' : '' } key={index}>{item.value} </p>)
}
</div>
</div>
);
}
}
ReactDOM.render( < App / > , document.querySelector("#app"))
body {
background: #20262E;
padding: 20px;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
.completed {
text-decoration: line-through;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="app"></div>
Check out this solution https://codesandbox.io/s/crazy-kare-go2vf
I have modified your code to achieve the required functionality.
This code does exactly what you want.
Update : Created a TODO fiddler code using React Hooks for modern code approach.
const initialState = {
items: [
{ text: "Learn JavaScript", done: false },
{ text: "Learn React", done: false },
{ text: "Play around in JSFiddle", done: true },
{ text: "Build something awesome", done: true }
]
};
function appReducer(state, action) {
switch (action.type) {
case 'ITEM_STATUS_CHANGE':{
let affected = state.items.slice();
affected[action.index].done = !affected[action.index].done;
return Object.assign({}, state, { items: affected });
}
case 'ADD_ITEM_TO_LIST':{
let affected = state.items.slice();
affected.push({ text: action.data, done : false})
return Object.assign({}, state, { items: affected });
}
default:
throw new Error();
}
}
function TodoApp(props){
const [state, dispatch] = React.useReducer(appReducer, initialState);
return (
<div>
<h2>Todos:
<input type="text" id="todoTextItem"/>
<button
onClick={()=>{
dispatch({
type: 'ADD_ITEM_TO_LIST',
data: window.todoTextItem.value
})
}}
>Add Item</button>
</h2>
<ol>
{state.items.map((item, index) => (
<li key={index}>
<label>
<input
type="checkbox"
checked={item.done}
onChange={()=>{
dispatch({
type: 'ITEM_STATUS_CHANGE',
index: index,
})
}}
/>
<span className={item.done ? "done" : ""}>{item.text}</span>
</label>
</li>
))}
</ol>
</div>
);
}
ReactDOM.render(<TodoApp />, document.querySelector("#app"))
and in CSS
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
li {
margin: 8px 0;
}
h2 {
font-weight: bold;
margin-bottom: 15px;
}
.done {
color: rgba(0, 0, 0, 0.3);
text-decoration: line-through;
}
input {
margin-right: 5px;
}
Explanation:
Basically i am creating a list with done boolean flag which is false by default, which helps to identify if the TODO items added to the list is finished or not using reducers. With that logic class .done is toggled. You can change the code according to your need by segregating TODO list from done list items while setting state
This is a Unit testable code by creating Jest snapshot. Never to manipulate DOM directly, which will defeat the purpose of React's snapshot testing.
Old fiddle code using Class Component.
Use this to compare and learn modern hooks concepts from class based.

Categories