React app, можно ли создать такой компонент?

Всем привет, столкнулся с дурацким хотением, а именно:
Можно ли в react-е сделать, что бы компонента возвращала измененную переменную ?
Есть родительская компонента

class Parent extends React.Component {

    constructor(props) {
        super(props);

        this.state = {
            value1: "",
            value2: "",
            value3: "",
        };

        this.handleOnClick = this.handleOnClick.bind(this);

        this.elements = [
            {
                className: "parent__input parent__input--1",
                type: "text",
                val: this.state.value1,
                placeholder: "placeholder1"
            },
            {
                className: "parent__input parent__input--1",
                type: "text",
                val: this.state.value2,
                placeholder: "placeholder2"
            },
            {
                className: "parent__input parent__input--1",
                type: "text",
                val: this.state.value3,
                placeholder: "placeholder3"
            },
        ]
    }

    handleOnClick() {
        console.log(this.state.value1, this.state.value2, this.state.value3);
    }

    render() {
        return (
            <>
                {this.elements.map((element, index) => {
                    return (<Child key={index} className={element.className} type={element.type} value={element.val}
                                   placeholder={element.placeholder}/>)
                })}

                <div style={{marginTop: "10px"}}>
                    <span onClick={this.handleOnClick}>Кнопка</span>
                </div>
            </>
        )
    }
}


Есть дочерня компонента

const Child = ({className, type, value, placeholder}) => {

    const [innerValue, setInnerValue] = useState(value);

    const handleOnChange = (e) => {
        setInnerValue(e.target.value)
    };

    return (
        <div className={"input"}>
            <input onChange={handleOnChange} className={"input__field" + (className ? ` ${className}` : '')} type={type ? type : 'text'}
                   value={innerValue}/>
            {placeholder && <span className={"input__placeholder"}>{placeholder}</span>}
        </div>
    )
};



this.state - эмитирует данные из редьюсера

this.state = {
            value1: "1",
            value2: "2",
            value3: "3",
        };



Проблема вот в чем, сейчас после заполнения полей и нажатии на кнопку в родительской компоненте, я как полагается не получу новые значения переменных (value1, value2, value3), можно ли как-то сделать, что бы дочерний компонент изменял ту переменную, которую я передаю в него через параметры ?

Сейчас пользуюсь, как мне кажется граблями:
Передаю функцию из родителя, которая принимает параметром новую строку и вызываю ее во время события onChange (при таком подходе, я не знаю какая именно это переменная изменяется), можно дочернему компоненту предавать индификатор этой переменной в роле id и его же передавать в родительскую функцию вторым параметром, но тогда нужно как то делать перебор каждой переменной, а это не удобно...



Я хочу добиться такого результата:
У меня есть массив переменных из редьюсера, которые отвечают за поля ввода, я с помощью map создаю компоненты, передаю им эти переменные из редьюсера, при заполнении эти переменные изменяются, после чего нажатием на кнопку отправляю эти переменные обратно в редюсер

Заранее спасибо.
  • Вопрос задан
  • 105 просмотров
Решения вопроса 1
rockon404
@rockon404 Куратор тега React
Frontend Developer
1 Не храните состояние форм в редьюсере. В большинстве случаев в этом нет необходимости.

2. Уберите внутреннее состояние значения value из Input. Сейчас у вас получается два источника правды, но для чего они вам, я полагаю, вы и сами не понимаете.

3. Старайтесь не нарушать нативных интерфейсов без необходимости.
Ваш код:
handleParentOnChange(id, newValue) {}
handleParentOnChange(e.target.id, e.target.value);

Как следовало сделать:
handleParentOnChange(e) {}
handleParentOnChange(e);

4. Оптимизируйте повторяющийся код в handleParentOnChange. И вместо id используйте атрибут name.
handleParentOnChange(e) {
  const { name, value } = e.target;
  this.setState({
    [name]: value,
  });
}
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
Robur
@Robur
Знаю больше чем это необходимо
То что вы делаете - это правильно. передавайте переменную и onChange, в нем меняйте эту переменную, храните все в стейте родителя. Если проблемы с тем чтобы в onChange поменять нужную переменную - это решаемо - это и решайте.
Так как вы хотите сделать тоже можно, но это будет даже не грабли а весьма плохой код, чтобы не плодить количество говнокода на планете, не буду объяснять как.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы