#javascript #reactjs #arraylist #array-map
#javascript #reactjs #arraylist #массив-карта
Вопрос:
итак, у меня есть отображаемый список, который был создан из массива, и у каждого элемента в списке есть кнопка меню, которая отображает модальный для каждого элемента, теперь проблема в том, что если я нажимаю на кнопку с индексом 0 вместо отображения только для индекса 0, он отображается для всех, то же самое для всех остальныхиндексы
import React, {useState} from 'react'
import ListModal from './listModal';
export const Todo = ({ Todos, deleteItem }) => {
const [show, setshow] = useState(false);
const unshow = () => {
setshow(current => !current)
}
return (
<ul>
{
Todos.map((item, index) => (
<li key={index}>
<button className="deleteBoard" onClick={unshow}>•••</button>
<span>{item}</span>
<ListModal value = {item} show={show} unshow = {unshow} />
</li>
))
}
</ul>
);
};
Для ListModal установлено значение display:»none», поэтому, когда я нажимаю на кнопку, она отображает список modal наоборот
import React, { useState } from 'react'
import firebase from 'firebase/app';
import { db } from '../Firebase/Firebase';
import { useRouteMatch } from 'react-router-dom';
const ListModal = ({ value, show, unshow }) => {
const [text, settext] = useState(value)
const styles = {
display: show ? 'flex' : 'none'
}
const textChange = (e) => {
settext(e.target.value)
}
return (
<div className="listModal" style={styles}>
<div className="listContent">
<textarea value={text} rows="6" onChange={textChange}></textarea>
<button>Save</button>
<button onClick={unshow}>Cancel</button>
</div>
<div className="listOption">
<ul>
<li onClick={() => {deleteItem(value);moveCard()}}>Delete</li>
</ul>
</div>
</div>
)
}
export default ListModal
Заранее спасибо, я не против переписать, пожалуйста, просто помогите мне. Спасибо
Ответ №1:
в родительском компоненте я настраиваю модальный и передаю значения
Todos.map((item, index) => (
<li key={index}>
<ListModal value={item}/>
</li>
))
Затем в дочернем компоненте я настроил функции открытия и закрытия
const [show, setshow] = useState(false);
const styles = {
display: show ? 'flex' : 'none'
}
const isOpen = () => {
setshow(show => !show);
}
после этого в дочернем компоненте вы можете отобразить информацию об элементе и кнопку с помощью onclick
//Whatever stuff you want to render from the passed in data
return (
<span>{value}</span>
<button onClick={() => {() => isOpen()}}>View</button>
<div className="listModal" style={styles}>
<div className="listContent">
<textarea value={text} rows="6" onChange={textChange}></textarea>
<button>Save</button>
<button onClick={unshow}>Cancel</button>
</div>
<div className="listOption">
<ul>
<li onClick={() => {deleteItem(value);moveCard()}}>Delete</li>
</ul>
</div>
</div>
)
Ответ №2:
Я бы посоветовал вам использовать следующий подход, который все еще можно улучшить:
- вместо
unshow
метода создайте два методаshowModal
иhideModal
const showModal = (item) => {
setSelectedTodo(item);
setshow(true);
}
const hideModal = () => {
setSelectedTodo('');
setshow(false);
}
- используйте другое useState для выбранного Todo
const [selectedTodo, setSelectedTodo] = useState('')
- после списка есть только один
ListModal
экземпляр, который получает элемент из состояния
...
<ul>
{
Todos.map((item, index) => (
...
))
}
</ul>
<ListModal value={selectedTodo} show={show} unshow = {hideModal} />
...
- при нажатии на любую кнопку передайте текущее
showModal
задание методу
<button className="deleteBoard" onClick={()=> showModal(item)}>•••</button>
Комментарии:
1. метод unshow выполняет точно то же самое, что и два рекомендованных вами метода, и не могли бы вы подробнее объяснить свое решение
2. причина, по которой я начал использовать этот метод вместо вашего заявленного метода, заключается в том, что я понял, что он замкнут и выполняет ту же функцию, но если вы считаете, что другой метод лучше, пожалуйста, объясните, почему, и я это исправлю
3. Конечно, итак, во-первых, он должен быть назван в зависимости от его функциональности, я думаю,
unshow
вы имеете в видуhide
, но этот метод не скрывает модальный, он переключает его, показывает и скрывает, поэтому мы можем назвать его toggleModal, например, во-вторых, зачем разделять его на два метода? в моем подходе мы добавляем больше логики при отображении модального (передача и настройка выбранного Todo), это необходимо только в show, поэтому нам нужен отдельный метод для выполнения логики show, однако есть несколько лучших подходов, которые требуют большего разделения, я предложил этот для простоты4. хорошо, теперь я понимаю, я действительно последовал вашему примеру и смог решить эту проблему, но я не изменил функцию unshow. Я опубликую свой ответ, а затем изменю его. Спасибо
Ответ №3:
Мне не нужно было ничего менять в моем компоненте listModal. Вот родительский компонент, в который я внес некоторые изменения
import React, { useState } from 'react'
import ListModal from './listModal';
export const Todo = ({ Todos, deleteItem }) => {
const [show, setshow] = useState(false);
const [selected, setselected] = useState("")
const toggle = () => {
setshow(show => !show)
}
const select = (item) => {
setselected(item)
}
return (
<>
<ul>
{
Todos.map((item, index) => (
<li key={index}>
<button className="deleteBoard" onClick={() => { toggle(); select(item) }}>•••</button>
<span>{item}</span>
</li>
))
}
</ul>
<ListModal val={selected} deleteItem={deleteItem} show={show} toggle={toggle} />
</>
);
};
Объяснение::
Вместо того, чтобы помещать listModal в метод map, создавая таким образом компонент listModal для каждого элемента, отображаемого в списке. Я оставил его вне метода map, поэтому у меня есть только один компонент listModal для каждого элемента в методе map. Все, что меняется, — это значения, отображаемые listModal .
Я также создал метод select, который принимает параметр (item), который является отображаемым значением, и сохраняет его в selected . выбранное — это состояние, затем я передал выбранное в listModal .
Это почти все, что я сделал, извините, если мое объяснение плохое.