0

这是我制作的代码笔,它显示了我正在尝试做的事情。
https://codepen.io/doliphin/pen/JjRbqJO

从 each 的本地范围<Block />,他们能够访问所有其他块的值。

但是,以下代码使用相同的思想,不允许从其本地范围<InputBlock />访问状态。valueLookup

具体来说,我正在查看InputBlock. 我添加了评论以显示我得到的输出。

import * as React from 'react';
import ContentEditable from "react-contenteditable";
import './UserInput.css';

function debug(header, value, footer) {
    // just a way of printing pretty debug stuff
}

const insertAndReturn = (someArray, item, index) => (
    // inserts item at index of someArray and returns it
);

const InputBlock = ({startText, blockId, valueLookup, setValueLookup}) => {
    const text = React.useRef(startText ? startText.toString() : '');
    const editableRef = React.useRef(null);

    const updateParent = (event) => {
        console.log(`updating parent of ${blockId}...`)
        setValueLookup( oldObject => {
            let returnObject = {};
            returnObject[blockId] = event.target.value;
            debug('updated object (within updateParent) = ', {...oldObject, ...returnObject});
            // -> updated object (within updateParent) = {<blockId>: <someString>}
            return {...oldObject, ...returnObject}
        })
        debug('valueLookup = ', valueLookup);
        // -> valueLookup = {}
    }

    const handleChange = (event) => {
        text.current = event.target.value;
        updateParent(event);
    }

    const handleBlur = (event) => {
        updateParent(event);
    }

    return (
        <ContentEditable
            className={"user-input"}
            html={text.current}
            innerRef={editableRef}
            onChange={handleChange}
            onBlur={handleBlur}
        />
    )
}

const UserInput = () => {
    // an array of all components to be rendered
    const [ blockArray, setBlockArray ] = React.useState([]);
    // an object containing the text value of all blocks
    const [ blockValues, setBlockValues ] = React.useState({});
    // an ordered list of blockIds 
    const [ idArray, setIdArray ] = React.useState([]);
    // just an ID counter quite obvious idk
    const [ lastId, setLastId ] = React.useState(0);

    const newId = (count=1) => {
        // generates a certain number of Ids
    };

    // create a default input block
    const newInputBlock = (id, startText="") => (
        <InputBlock
            startText={startText}
            blockId={id}
            valueLookup={blockValues}
            setValueLookup={setBlockValues}
        />
    )

    // insert a block
    const insertBlock = (position, block) => {
        let blockId = newId();
        // fixes the position so that it always works
        if ( position > blockArray.length || position === "end" ) { 
            position = blockArray.length;
        };
        if ( position < 0 ) { position = 0 };
        // default block
        if ( !block ) {
            block = <div style={{display: "inline-block"}}>
                {newInputBlock(blockId, "")}
            </div>
        }
        // updates the ordered states
        setBlockArray( oldArray => insertAndReturn(oldArray, block, position) );
        setIdArray( oldArray => insertAndReturn(oldArray, blockId, position) );
    } 

    return <div>
        {blockArray}
    </div>
}

export default UserInput

为什么此代码的工作方式与我的 codepen 不同?(道具始终是最新的并且可以在本地访问)

4

1 回答 1

0

如果我理解您正在尝试正确执行的操作setValueLookup是异步的,那么您在设置后立即检查它同步设置的状态,这将无法获取当前值。

于 2020-12-12T02:33:52.720 回答